使用pandas进行数据处理有一段时间了,对我遇到的数据读取方面的问题和解决手段进行如下汇总。
数据读取:
1.读取Excel文件
read_csv Unicode DecodeError:‘utf-8’ codec can not decode byte 0xb1 in position 0 :invalid start byte。
编码问题:一般Excel的默认编码为ANSI, 这是微软规定的一种编码,我们在读取的时候需要指定。read_csv('文件路径',encoding = ‘ANSI’)
2.读取txt文件
问题一:仍然是编码问题,只不过改成GBK了
问题二:使用分割符问题,导致按行读取没分割开
问题三:表头加入问题
我使用的按行存储数据的txt ,每行为一条记录,字段使用 \t 分割。编码集转换为了utf-8
因此按以下方法读取进DataFrame:
df = pd.read_csv(file_uri, sep='\t',encoding='utf-8',names=title_names)
值得一提的是,read_csv默认sep为‘,’,如果读进来的数据结构乱了的话,先查看分割符问题。此外,使用df = pd.read_table(file_uri,encoding='utf-8',names=title_names)也是可以的,read_table方法是默认使用‘\t’作为分割符的。
表头加入只需要定义一个数组,传给names参数即可。
3.写入Excel文件
写入符合条件的某几列,例如写入第一季度的数据:
temp =df.loc[df['month'].isin(['03','04','05'])];
temp.to_excel(file_uri,sheet_name='season one')
写入groupby后的数据:需求为假设按照分公司分组,我们要写入各个公司金额数,违规收入金额占比,记录数,违规记录占比,那么我们是按列写入还是拼成DataFrame后写入呢?
如果是使用pd.DataFrame.to_excel()的方法,我们必须拼接DataFrame,否则只能自定义函数写入。
为了拼接成DataFrame,我们将每个values数组转化成Series,然后使用concat函数进行axsi=1也就是列方向上的拼接。
计算百分占比
使用Series进行加减乘除运算,axis=0,然后使用map函数套format输出百分比。具体操作代码如下:
# 公司名
company_name = pd.Series(df.groupby(['分公司']).sum().index.values)
# 计算违规金额比例
notNormal_money_total = pd.Series((df.loc[df['收费类型(正常,违规,假冒)'] != '正常']).groupby(['分公司'])['金额'].sum().values)
money_total = pd.Series(df.groupby(['分公司'])['金额'].sum().values)
ratio_notNormal_money(notNormal_money_total.div(money_total,axis=0) ).map(lambda x: "{:.2%}".format(x))
# 计算违规条数比例
notNormal_record = pd.Series((df.loc[df['收费类型(正常,违规,假冒)'] != '正常']).
groupby(['分公司'])['金额'].count().values)
record_total = pd.Series(df.groupby(['分公司'])['金额'].count().values)
ratio_notNormal_record = (notNormal_record.div(record_total,axis=0)).map(lambda x: "{:.2%}".format(x))
# 写入Excel表格
lvtong_excel = './lvtong_analysis.xlsx'
names_list = ['分公司名','总金额','非法金额','非法金额占比','总记录数','非法记录数','非法记录占比']
companydf = pd.concat([company_name,money_total,notNormal_money_total,ratio_notNormal_money, record_total,notNormal_record,ratio_notNormal_record], axis=1)
companydf.columns = names_list
companydf.to_excel(lvtong_excel,sheet_name='公司维度表')