在项目开发过程中或者工作中,我们经常会分析和处理数据,使用pandas可以大大的提高分析和处理数据的效率,本文主要是将数据分析和处理过程中常用的方法以及经验做一个记录。
pandas官方Get Start使用文档:https://pandas.pydata.org/docs/getting_started/index.html
pandas官方接口文档:https://pandas.pydata.org/docs/reference/
首先安装python环境,之前有介绍过如何在windows上安装python环境,不清楚的同学可以参考下。然后直接通过pip命令安装最新版本的pandas,安装命令如下:
pip install pandas
读取excel需要依赖xlrd,根据需要安装:
pip install xlrd
一般情况,我们的工作中的数据会存储在Excel或者文本文件的情况较多,开发性质的数据会存储在数据库中,这里主要介绍pandas读取Excel和文本文件的方式。
通过read_csv方法读取csv或者txt的文件(也可以通过read_table方法读取),read_csv方法的参数如下,详细介绍参考官网说明:
pandas.
read_csv
(filepath_or_buffer, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)
参数中我们可能用得较多的有sep分割符(默认','),header列名(默认infer自动推测), names自定义列名(默认None不设置) ,usecols指定列(默认None不指定),encoding编码格式(默认None,utf-8),error_bad_lines行数据错误抛出异常(默认True抛出异常)。
指定编码格式,不读取csv文件第一行作为列名以及忽略行数据错误的示例:
import pandas as pd
df_data = pd.read_csv('test.csv', header=0, error_bad_lines=False, encoding="GB2312")
自定义列名的示例:
import pandas as pd
df_data = pd.read_csv('test.csv', header=0, names=['id', 'email', 'status', 'valid', 'result'], error_bad_lines=False, encoding="GB2312")
只读取前两列的示例:
import pandas as pd
df_data = pd.read_csv('test.csv', header=0, names=['id', 'email'], usecols=[0,1], error_bad_lines=False, encoding="GB2312")
通过read_excel方法读取excel文件,详细介绍参考官网说明,参数如下:
pandas.
read_excel
(*args, **kwargs)
参数中我们可能用得较多的有sheet_name表名,header列名, names自定义列名 ,usecols指定列。
示例:
import pandas as pd
df_data = pd.read_excel('test.xls', header=0, names=['id', 'email'], usecols=[0,1])
通过read_csv或者read_excel方法我们可以将文件的数据读取到DataFrame中,然后就可以通过pandas进行数据分析以及处理。
通过pandas对数据进行分析以及处理后,我们一般会将最终的数据输出到文件中。常用的保存数据方法有to_csv保存为文本文件:
DataFrame.
to_csv
(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', line_terminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict')
参数中我们可能用得较多的有sep分割符(默认','),header输出列名,,index输出索引 ,mode写入模式,encoding编码格式(默认None,utf-8)。
以','分割列,不输出索引和列名的示例:
df_data.to_csv('result.csv', header=None, index=False, sep=',', encoding='utf8')
我们也可以使用python内置的open方法来保存文本文件,使用open方法会更灵活的保存数据,当然首先建议使用pandas的to_csv方法,如果无法满足我们再使用python内置的open方法来一行一行的保存文件。如下是一行一行的存储json格式的数据示例:
with open(file_path, mode='w', encoding='utf8') as fo:
for item in dict_data:
line = json.dumps(item)
fo.write(line + '\n')
当我们需要处理的数据在多个文件中时,我们需要把数据合并之后再进行处理,这时需要用到pandas.concat方法,concat方法的详细说明参考官网。
pandas.
concat
(objs: Union[Iterable[‘DataFrame’], Mapping[Label, ‘DataFrame’]], axis='0', join: str = "'outer'", ignore_index: bool = 'False', keys='None', levels='None', names='None', verify_integrity: bool = 'False', sort: bool = 'False', copy: bool = 'True') → ’DataFrame’
读取目录下的所有csv文件进行处理,先通过pandas将一个个csv文件读取到DataFrame中放入list,然后通过pandas的concat合并list中的DataFrame数据,然后再进行数据处理和分析,主要代码示例如下:
def email_handle(input_path):
files = os.listdir(input_path)
input_files = list(filter(lambda x:(x[-len('csv'):] == 'csv'), files))
df_list = []
for input_file in input_files:
df_item = pd.read_csv(input_path + input_file, header=0, names=['email', 'repair_email', 'repair_flag'], usecols=[0,1,2], encoding='utf8')
df_list.append(df_repair_item)
df_data = pd.concat(df_list)
pandas中有多种方法可以实现查询,这里介绍博主常用的方法,按照条件查询(单条件、多条件、并且、或者),获取部分列的数据,示例如下:
def email_handle(input_path):
files = os.listdir(input_path)
input_files = list(filter(lambda x:(x[-len('csv'):] == 'csv'), files))
df_list = []
for input_file in input_files:
df_item = pd.read_csv(input_path + input_file, header=0, names=['email', 'repair_email', 'repair_flag'], usecols=[0,1,2], encoding='utf8')
df_list.append(df_repair_item)
df_data = pd.concat(df_list)
# 获取repair_flag为1的数据
df_data_tmp = df_data[df_data['repair_flag'] == 1]
# 获取repair_flag为1并且repair_email包含@qq.com的数据
df_data_tmp = df_data[(df_data['repair_flag'] == 1) & (df_data['repair_email'].str.contains('@qq.com'))]
# 获取repair_flag为1或者2的数据
df_data_tmp = df_data[(df_data['repair_flag'] == 1) | (df_data['repair_flag'] == 2)]
df_data_tmp = df_data[df_data['repair_flag'].isin([1,2]]
# 获取repair_flag为1的repair_email列数据
df_data_tmp = df_data.loc[df_data['repair_flag'] == 1, ['repair_email']]
我们处理的数据很有可能包含一些重复的数据,一般博主使用drop_duplicates方法去重,详细介绍参考官网:
DataFrame.
drop_duplicates
(subset=None, keep='first', inplace=False, ignore_index=False)
将原数据中按照email列去重,只保留第一行的数据示例:
def email_handle(input_path):
files = os.listdir(input_path)
input_files = list(filter(lambda x:(x[-len('csv'):] == 'csv'), files))
df_list = []
for input_file in input_files:
df_item = pd.read_csv(input_path + input_file, header=0, names=['email', 'repair_email', 'repair_flag'], usecols=[0,1,2], encoding='utf8')
df_list.append(df_repair_item)
df_data = pd.concat(df_list)
# 按照email列去重,保留第一行数据
df_data.drop_duplicates(subset=['email'], keep='first', inplace=True)
使用groupby分组后按照数量多少排序后去重,先groupby分组,然后安装count列倒序,然后删除count列实现将重复数量由多到少排序去重,示例代码如下:
pd_data = pd_data.groupby('email')['repair_email'].count().reset_index(name='count')
pd_data = pd.DataFrame(pd_data)
pd_data = pd_data.sort_values('count', ascending=False).drop('count', axis = 1)
处理数据之后,我们可能会重命名列名,然后再将处理后的数据输出到文件中,这时我们需要重命名列名,使用rename方法实现。
df_data.rename(columns={'email':'old_email', 'repair_email':'new_email'}, inplace = True)
在处理数据的过程中,我们可能会增加一些列来存储一些数据或者作为临时中转使用,这时需要增加列,增加列的方式有多种。下面是一些常用的示例:
# 增加status列并设置为0
df_data['status'] = 0
# 增加status列,根据err_flag设置值
df_data['status'] = df_data['err_flag'].apply(lamdba x : x if x == 1 else 0)
# 增加status列,err_flag的值 加 10
df_data['status'] = df_data['err_flag'] + 10
如果增加的列的值是通过比较复杂的计算而来,可以自定义方法结合apply方式增加列示例:
def get_status(series, unknow=0):
if pd.isna(series['err_flag']):
return unknow
status = unknow
if series['err_flag'] == 1:
status = 1
elif series['email'] == series['repair_email']:
status = 1
else:
status = unknow
return status
# 增加一列status, 使用get_status方法获取status的值
df_data['status'] = df_data.apply(get_status, axis=1, args=(0,))
我们通过数据加工和处理后,可能需要输出类似json的数据格式,这时候我们需要to_dict方法将数据转换为dict字典格式的数据,然后再讲dict字典格式的数据转为json格式的数据输出到文本文件。
# 将DateFrame装为dict字典格式数据, records可以看做每行数据一个对象
dict_data= df_data.to_dict('records')
# 将每行数据转为json字符串之后存入文本
with open(file_path, mode='w', encoding='utf8') as fo:
for item in dict_data:
line = json.dumps(item)
fo.write(line + '\n')
输出到文本的数据格式如下所示,每行数据为json格式。
{"email": "[email protected]", "repair_email": "[email protected]", "err_flag": 1}
{"email": "[email protected]", "repair_email": "[email protected]", "err_flag": 1}
{"email": "[email protected]", "repair_email": "[email protected]", "err_flag": 1}
{"email": "[email protected]", "repair_email": "[email protected]", "err_flag": 1}
{"email": "[email protected]", "repair_email": "[email protected]", "err_flag": 1}
掌握了pandas常用的一些方法后,大大提高了对于数据的分析和处理的效率。自我感觉使用Python的pandas对于数据处理以及加工比使用.NET和Java高效很多,编码的工作大幅减少,作为工具非常实用。本文是博主在使用pandas处理数据过程中的一些总结和分享,希望能给其他同学提供一些帮助。如果有描述不准确的地方,欢迎指正。