Pandas数据处理方法(包括数据库数据和普通文件数据)
pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。
Pandas中常见的数据结构有两种:
Series | DataFrame |
---|---|
类似一维数组的对象 | 类似多维数组/表格数组,每列数据可以是不同的类型;索引包括行索引和列索引 |
Series
构建Series:ser_obj = pd.Series(range(10));
由索引和数据组成(索引在左<自动创建的>,数据在右);
获取数据和索引:ser_obj.index; ser_obj.values;
预览数据: ser_obj.head(n);ser_obj.tail(n)DateFrame
获取列数据:df_obj[col_idx]或df_obj.col_idx;
增加列数据:df_obj[new_col_idx] = data;
删除列:del df_obj[col_idx];
按值排序:sort_values(by = “label_name”)
常用方法:
Count | 非NA值得数量 |
---|---|
describe | 针对Series或各DataFrame列计算汇总统计 |
min/max | 计算最小值/最大值 |
argmin/argmax | 计算能够获取到最小值/最大值的索引位置 |
idxmin/idxmax | 计算能够获取到最小值/最大值的索引值 |
quantile | 计算样本的分位数(0-1) |
sum | 值的总和 |
mean | 值的平均数 |
median | 值的算术中位数(50%分位数) |
mad | 根据平均值计算平均绝对离差 |
var | 样本值的方差 |
std | 样本值的标准差 |
skew | 样本值的偏度(三阶距) |
kurt | 样本值的峰度(四阶距) |
cumsum | 样本值的累计和 |
cummin/cummax | 样本值的累计最小值和累计最大值 |
diff | 计算一阶差分(对时间序列很有用) |
pct_change | 计算百分数变化 |
处理丢失数据
dropna() 丢弃缺失数据;
fillna() 填补缺失数据数据过滤
df[filter_condition] 依据filter_condition(条件)对df进行过滤
读写不同数据源的数据
1.数据库数据读取
pandas提供了读取与存储关系型数据库数据的函数与方法。除了pandas库外,还需要使用SQLAIchemy库建立对应的数据库连接。SQLAIchemy配合相应数据库的Python连接工具(例如MySQL数据库需要安装mysqlclient或者pymysql库),使用create_engine函数,建立一个数据库连接。
creat_engine 中填入的是一个连接字符串。在使用Python的SQLAlchemy时,MySQL和Oracle数据库连接字符串的格式如下:
数据库产品名+连接工具名: //用户名:密码 @ 数据库IP地址:数据库端口号/数据库名称? charset = 数据库数据编码
read_sql_table只能够读取数据库的某一个表格,不能实现查询的操作。
pandas.read_sql_table(table_name, con, schema=None, index_col=None,coerce_float=True, columns=None)read_sql_query则只能实现查询操作,不能直接读取数据库中的某个表。
pandas.read_sql_query(sql, con, index_col=None, coerce_float=True)read_sql是两者的综合,既能够读取数据库中的某一个表,也能够实现查询操作。
pandas.read_sql(sql, con, index_col=None, coerce_float=True, columns=None)
pandas三个数据库数据读取函数的参数几乎完全一致,唯一的区别在于传入的是语句还是表名。
2.数据库数据存储
数据存储只有一个to_sql方法。
DataFrame.to_sql(name, con, schema=None, if_exists='fail’, index=True, index_label=None, dtype=None)
3.读写文本文件
(1)文本文件读取
文本文件是一种由若干行字符构成的计算机文件,它是一种典型的顺序文件。
csv是一种逗号分隔的文件格式,因为其分隔符不一定是逗号,又称为字符分隔文件,文件以纯文本形式存储表格数据(数字和文本)
使用read_table来读取文本文件
pandas.read_table(filepath_or_buffer, sep=’\t ', header='infer’, names=None, index_col=None,
dtype=None, engine=None, nrows=None)使用read_csv函数来读取csv文件。
pandas.read_csv(filepath_or_buffer, sep=’\t ', header='infer ', names=None, index_col=None,dtype=None, engine=None, nrows=None)
read_table和read_csv常用参数及其说明。
read_table和read_csv函数中的sep参数是指定文本的分隔符的,如果分隔符指定错误,在读取数据的时候,每一行数据将连成一片。
header参数是用来指定列名的,如果是None则会添加一个默认的列名。
encoding代表文件的编码格式,常用的编码有utf-8、utf-16、gbk、gb2312、gb18030等。如果编码指定错误,数据将无法读取,IPython解释器会报解析错误。
4.文本文件存储
文本文件的存储和读取类似,结构化数据可以通过pandas中的csv文件格式存储。
DataFrame.to_csv(path_or_buf=None, sep=’,’,na_rep=’’, columns=None, header=True)
5.Excel文件读取
pandas提供了read_excel函数来读取“xls” "xlsx"两种Excel文件。
pandas.read_excel(io, header=0, sheetname=0, index_col=None, names=None, dtype=None)
6.Excel文件存储
将文件存储为Excel文件,可以使用to_excel。
DataFrame.to_excel(excel_writer=None, sheetname=None, na_rep=’’,header=True, index=True, index_label=None, mode='w’, encoding=None)
to_csv方法的常用参数基本一致,区别之处在于指定存储文件的文件路径参数名称为excel_writer,并且没有sep参数,增加了一个sheetnames参数用来指定存储的Excel sheet的名称,默认为sheet1。
DataFrame的常用操作
基础属性
函数 | 返回值 |
---|---|
values | 元素 |
index | 索引 |
columns | 列名 |
dtypes | 类型 |
size | 元素个数 |
ndim | 维度数 |
shape | 数据形状(行列数目) |
增删改查DataFrame数据
1. 查看访问DataFrame中的数据——数据基本查看方式
对单列数据的访问:DataFrame的单列数据为一个Series。根据DataFrame的定义可以知晓DataFrame是一个带有标签的二维数组,每个标签相当于每一列的列名。有以下两种方式来实现对单列数据的访问:
(1)以字典访问某一个key的值的方式使用对应的列名,实现单列数据的访问。
(2)以属性的方式访问,实现单列数据的访问。(不建议使用,易引起混淆)
对某几行访问:
df[1:4], head(n), tail(n)
loc和iloc方法
loc方法是针对DataFrame索引名称的切片方法,如果传入的部署索引名称,那么切片操作将无法执行。利用loc方法,能够实现所有单层索引切片操作。
df.loc[行索引名称或条件,列索引名称]
df.iloc[行索引位置,列索引位置]
iloc和loc区别是iloc接收的必须是行索引和列索引的位置。
使用loc和iloc实现多列切片,其原理的通俗解释就是将多列的列名或者位置作为一个列表或者数据传入。
使用loc、iloc方法可以取出DataFrame中的任意数据。
loc使用传入的行索引名称如果是一个区间,前后均为闭区间;iloc为前闭后开区间。
loc内部还可以传入表达式,结果会返回满足表达式的所有值。
具体例子可见这篇博文https://blog.csdn.net/ITmincherry/article/details/109577480
若使用detail.iloc[detail['order_id’]=='458’,[1,5]]读取数据,会报错,原因在于此处条件返回的是一个布尔值Series,而iloc可以接收的数据类型不包括Series。根据Series的构成只要取出该Series的values就可以了。需改为detail.iloc[(detail['order_id’]=='458’.values[1,5]])
loc更加灵活多变,代码的可读性更高,iloc的代码简洁,但可读性不高。具体用哪个视情况而定,大多数时候建议使用loc方法。
切片方法之ix
ix方法像是loc和iloc两种切片方法的融合,ix使用时既可以接收索引名称也可以接收索引位置。
df.ix[行索引的名称或位置或条件,列索引名称或位置]
使用ix方法有几个注意事项:
当索引名称和位置存在部分重叠时,ix默认优先识别名称;
使用ix参数时,尽量保持行索引名称和行索引位置重叠,使用时就无须考虑取值时区间的问题,一律为闭区间。
使用列索引名称,而非列索引位置,主要用来保证代码可读性。
使用列索引位置时,需要注解,同样保证代码可读性。
ix还有一个缺点,就是在面对数据量巨大的任务的时候,其效率会低于loc和iloc方法,所以在日常的数据分析工作中建议使用loc和iloc方法来执行切片操作。
2.更新修改数据
数据修改直接针对DataFrame原数据更改,操作无法撤销,如果作出更改,需要对更改条件做确认或对数据进行备份。
3.增加数据
新建一个列索引,对该索引下的数据赋值操作即可。
新增的一列值是相同的则直接赋值一个常量即可。
4.删除某列或某行数据
drop(labels, axis=0, level=None, inplace=False, errors='raise’)
axis为0时表示删除行,axis为1表示删除列。
常用参数如下:
描述分析DataFrame数据
数值型特征的描述性统计
1、Numpy中的描述性统计函数
数值型数据的描述性统计主要包括了计算数值型数据的完整情况、最小值、均值、中位数、最大值、四分位数、极差、标准差、方差、协方差和变异系数等。一些常用的统计学函数如下表所示。
2、pandas描述性统计方法
pandas库基于numpy,也可以用上面那些函数对数据框进行描述性统计。
pandas还提供了更加便利的方法来计算均值,如detail['amounts’].mean()
pandas还提供一个方法叫做describe,能够一次性得出数据框所有数值型特征的非空值数目、均值、四分位数、标准差。
2.类别型特征的描述性统计
描述类别型特征的分布状况,可以使用频数统计表。pandas库中实现频数统计的方法为value_counts。
pandas提供了categories类,可以使用astype方法将目标特征的数据类型转换为category类别。
describe方法除了支持传统数值型以外,还能够支持对category类型的数据进行描述性统计,四个统计量分别为列非空元素的数目、类别的数目、数目最多的类别、数目最多类别的数目。
转换与处理时间序列数据
转换字符串时间为标准时间
1、pandas时间相关的类
在多数情况下,对时间类型数据进行分析的前提是将原本为字符串的时间转换为标准时间类型。pandas继承了Numpy库和datatime库的时间相关模块,提供了6种时间相关的类。
类名称 | 说明 |
---|---|
Timestamp | 最基础的时间类,表示某个时间点。在绝大多数的场景中的时间数据都是Timestamp形式的时间 |
Period | 表示单个时间跨度,或者某个时间段,例如某一天、某一小时等 |
Timedelta | 表示不同单位的时间,例如1天、1.5小时 |
DatetimeIndex | 一组Timestamp构成的index,可以用来作为Series或DataFrame的索引 |
PeriodtimeIndex | 一组period构成的index,可以用来作为Series或者DataFrame的索引 |
TimedeltaIndex | 一组Timedelta构成的index,可以用来作为Series或者DataFrame的索引。 |
其中Timestamp作为时间类中最基础的,也是最为常用的。在多数情况下,时间相关的字符串都会转换成为Timestamp,pandas提供了to_datetime函数,能够实现这一目标。值得注意的是,Timestamp类型时间是有限制的。
除了将数据自原始DataFrame中直接转换为Timestamp格式外,还可以将数据单独提取出来将其转换为DatatimeIndex或者PeriodIndex。
转换为PeriodIndex的时候需要注意,需要通过freq参数指定时间间隔,常用的时间间隔有Y为年,M为月,D为日,H为小时,T为分钟,S为秒。两个函数可以用来转换数据还可以用来创建时间序列数据,其参数非常类似。
Datetimelndex和PeriodIndex两者区别在日常使用的过程中相对较小,其中 Datetimelndex是用来指代一系列时间点的一种数据结构,而 PeriodIlndex则是用来指代一系列时间段的数据结构。
提取时间序列数据信息
在多数涉及时间相关的数据处理,统计分析的过程中,需要提取时间中的年份,月份等数据。使用对应的Timestamp类属性就能够实现这一目的。
结合Python列表推导式,可以实现对DataFrame某一列时间信息数据的提取。
在DatetimeIndex和PeriodIndex中提取对应信息可以以类属性方式实现。
值得注意的是PeriodIndex相比于DatetimeIndex少了weekday_name属性,所以不能用该属性提取星期名称数据。若要提取信息名称可以通过提取weekday属性,而后将0-6四个标签分别赋值为Monday至Sunday。
Timedelta是时间相关的类中的一个异类,不仅能够使用正数,还能够使用负数表示单位时间。例如1秒等。Timedelta函数中时间周期中没有年和月,所有周期名称,对应单位和说明如下表所示:
使用Timedelta,可以很轻松地实现在某个时间上加减一段时间。
除了使用Timedelta实现时间的平移外,还能够直接对两个时间序列进行相减,从而得出一个Timedelta.
使用分组聚合进行组内计算
使用groupby方法拆分数据
该方法提供的是分组聚合步骤中的拆分功能,能根据索引或字段对数据进行分组。其常用参数与使用格式如下,df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)
如果传入的是一个函数则对索引进行计算并分组;
如果传入的是一个字典或者Series,则字典或者Series的值用来做分组依据;
如果传入一个Numpy数组则数据的元素作为分组依据;
如果传入的是字符串或者字符串列表则使用这些字符串所代表的字段作为分组依据。
用groupby方法分组后的结果并不能直接查看,而是被存在内存中,输出的是内存地址。实际上分组后的数据对象groupby类似Series与DataFrame,是pandas提供的一种对象。
使用agg方法聚合数据
agg和aggregate方法都支持对每个分组应用某函数,包括Python内置函数或自定义函数。同时这两个方法也能够直接对DataFrame进行函数应用操作。
在正常使用过程中,agg函数和aggregate函数对DataFrame对象操作时功能几乎完全相同,因此只需要掌握其中一个函数即可。
df.agg(func, axis=0, *args, **kwargs)
df.aggregate(func, axis=0, *args, **kwargs)
agg方法求统计量
使用agg一次求出当前数据中所有菜品销量和售价的总和与均值,如detail[['counts’,'amounts’]].agg([np.sum,np.mean]))
对某个字段只做求均值操作,对另一个字段只做求和操作,可以使用字典,如detail.agg({'counts’:np.sum,'amounts’:np.mean})
有时要求出某个字段的多个统计量,某些字段只需要求一个统计量,此时只需要将字典对应key的value变为列表,列表元素为多个目标的统计量即可。如detail.agg({'counts’:np.sum,'amounts’:[np.mean,np.sum]})
agg方法与自定义函数
agg方法可传入自定义函数,需要注意的是numpy库中的函数,np.mean,np.median,np.prod,np.std,np.var能够在agg中直接使用,但是在自定义函数中使用numpy库中的这些函数,如果计算的时候是单个序列则会无法得出想要的结果,如果是多列数据同时计算则不会出现这种问题。
使用agg可以实现对每一个字段每一组使用相同的函数,如果需要对不同的字段应用不同的函数,则可以和DataFrame中使用agg方法相同。
使用apply方法聚合数据
apply类似agg能够将函数应用于每一列,不同之处在于apply相比agg传入的函数只能够作用于整个DataFrame或者Series,而无法像agg一样能够对不同字段,应用不同函数获取不同结果。
使用apply对groupby对象进行聚合操作其方法和agg方法也相同,只是使用agg方法能够实现对不同字段进行应用不同的函数,而apply不行。
使用transform聚合数据
transform能够对整个DataFrame的所有元素进行操作,且transform只有一个参数func,表示对DataFrame操作的函数。
transform还能对DataFrame分组后的对象groupby进行操作,可以实现组内离差标准化等操作。
若在计算离差标准化的时候结果中有NaN,这是由于根据离差标准化公式,最大值和最小值相同的情况下分母是0.
创建透视表与交叉表
使用povit_table创建透视表
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean’, fill_value=None, margins=False, dropna=True, margins_name='All’)
在不特殊指定聚合函数aggfunc时,会默认使用numpy.mean进行聚合运算,numpy.mean会自动过滤掉非数值类型数据。可以通过指定aggfunc参数修改聚合函数。
和groupby分组的时候相同,pivot_table函数在创建透视表的时候分组键index可以有多个。
通过设置columns参数可以指定列分组。
当全部数据列数很多时,若只想要显示某列,可以通过指定values参数来实现。
当某些数据不存在时,会自动填充NaN,因此可以指定fill_value参数,表示当存在缺失值时,以指定数值进行填充。
可以更改margins参数,查看汇总数据。
使用crosstab创建交叉表
交叉表是一种特殊的透视表,主要用于计算分组频率。利用pandas提供的crosstab函数可以制作交叉表。
由于交叉表是透视表的一种,其参数基本保持一致,不同之处在于crosstab函数中的Index,columns,values填入的都是对应的从DataFrame中取出的某一列。
pandas.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
crosstab常用参数及其说明: