最后一次更新日期: 2019/3/21
pandas
是基于numpy
的数据分析库,提供一些更易用的数据模型和大量高效的统计方法。
使用前先导入模块:
import pandas as pd
按需导入以下模块:
import numpy as np
import matplotlib.pyplot as plt
1. 运算符和标量值函数
pandas重载了python的大部分运算符,可以直接进行数组计算,numpy的标量值函数也可直接使用,这些运算都是将原本作用于单个元素的运算拓展到整个数组。
In [56]: df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])
In [57]: df+df
Out[57]:
col1 col2
0 2 22
1 6 aa
In [201]: np.sqrt(df.col1)
Out[201]:
0 1.000000
1 1.732051
Name: col1, dtype: float64
使用的运算符和函数必须对参与运算的所有数据类型都是有意义的,否则会报错。
匹配方式
In [154]: s1=pd.Series([1,2,3,4],index=[0,1,2,3])
In [155]: s2=pd.Series([5,6,7,8],index=[1,2,3,4])
In [156]: s1+s2
Out[156]:
0 NaN
1 7.0
2 9.0
3 11.0
4 NaN
dtype: float64
此处需要注意pandas和numpy的区别,pandas的数组运算在元素匹配上是基于标签索引的,未能匹配到的位置会被替换为NaN,numpy则是基于位置索引。
2. 统计方法
聚合函数
pandas继承了numpy的聚合函数:sum
、mean
、max
、min
等。
可通过Series
和DataFrame
的方法调用,或是调用numpy下的静态方法。
In [58]: df.sum()
Out[58]:
col1 4
col2 2a
dtype: object
In [60]: np.max(df)
Out[60]:
col1 3
col2 a
dtype: object
In [114]: df.agg({'col1':'max','col2':'sum'})
Out[114]:
col1 3
col2 2a
dtype: object
In [115]: df.agg(['max','sum'])
Out[115]:
col1 col2
max 3 a
sum 4 2a
通过pandas数据模型的方法调用时,
第一个参数axis
可以指定统计的轴,Series
指定该参数没有意义,DataFrame
默认沿轴0统计,即按列统计。pandas无法指定对所有轴展开统计,如有需要可以使用numpy的方法;
第二个参数skipna
可以指示是否跳过NaN
值;
第三个参数level
用于在存在多级索引的情况下指定某一级索引进行统计;
第四个参数numeric_only
用于指定是否只对数字应用计算。
当对DataFrame
沿行方向统计时,由于不同列的数据类型可能不一样,需保证对应运算是有意义的,否则无法得到期望的结果。
agg
方法是aggregate
方法的简写,用于对不同列应用不同聚合函数或是多种聚合函数,可以传入list
或是dict
声明统计方式。
分组统计
pandas提供了类似于sql的groupby
方法用于分组统计。
In [88]: df=pd.DataFrame([['a','c',1],['a','d',2],['b','d',3]],columns=['col1','col2','col3'])
In [89]: df
Out[89]:
col1 col2 col3
0 a c 1
1 a d 2
2 b d 3
In [93]: result=df.groupby(by=['col1','col2']).agg(['max','min'])
In [94]: result
Out[94]:
col3
max min
col1 col2
a c 1 1
d 2 2
b d 3 3
In [95]: result.sum(level=0)
Out[95]:
col3
max min
col1
a 3 3
b 3 3
In [140]: gb=df.groupby(by=['col1','col2'])
In [141]: gb.groups
Out[141]:
{('a', 'c'): Int64Index([0], dtype='int64'),
('a', 'd'): Int64Index([1], dtype='int64'),
('b', 'd'): Int64Index([2], dtype='int64')}
In [142]: gb.get_group(('a','c'))
Out[142]:
col1 col2 col3
0 a c 1
只调用groupby
方法会得到一个DataFrameGroupBy
对象,通过其groups
方法可查看所有分组信息,get_group
方法可获取指定分组。
该对象可调用各种聚合函数,或调用agg
方法进行复合的聚合统计,返回包含多级索引的DataFrame
统计结果表,对于结果表,可以继续应用统计函数并通过level
参数指定索引级别进行二次统计。
3. 应用自定义函数
除pandas和numpy提供的函数外,还可以自定义函数并使用apply
、applymap
、map
方法快速应用于整个数据集。
In [119]: df.apply(lambda x: x.col1+x.col2, axis=1)
Out[119]:
0 3
1 7
dtype: int64
In [120]: def add(row):
...: return row.col1+row.col2
In [121]: df.apply(add, axis=1)
Out[121]:
0 3
1 7
dtype: int64
In [122]: df.applymap(lambda x: x*2)
Out[122]:
col1 col2
0 2 4
1 6 8
In [123]: def double(item):
...: return item*2
In [124]: df.applymap(double)
Out[124]:
col1 col2
0 2 4
1 6 8
In [128]: s=pd.Series(['a','b','b'])
In [129]: s.map(lambda x: x*2)
Out[129]:
0 aa
1 bb
2 bb
dtype: object
In [130]: s.map({'a':'c','b':'d'})
Out[130]:
0 c
1 d
2 d
dtype: object
DataFrame
有apply
和applymap
两个方法:
apply
将函数应用于每行或者每列,axis
参数指定应用函数的轴方向,值为0表示按列应用,即逐列作为函数的参数进行计算,值为1表示按行应用,默认为0;
applymap
将函数应用于每个元素。
Series
只有一个map
方法,用于将函数应用于元素,除此以外,还提供值映射的功能,输入dict
类型时会根据key-value映射将相应的值替换。
支持lambda匿名函数。
4. 广播
In [80]: l2=[1,2]
...: a2=np.array(l2)
...: s2=pd.Series(l2)
...: df21=pd.DataFrame([1,2])
...: df12=pd.DataFrame([[1,2]])
...: l22=[[1,2],[3,4]]
...: a22=np.array(l22)
...: df22=pd.DataFrame(l22)
...: df23=pd.DataFrame([[3,4,5],[6,7,8]])
In [99]: df22+l2
Out[99]:
0 1
0 2 4
1 4 6
In [100]: df22+a2
Out[100]:
0 1
0 2 4
1 4 6
In [101]: df22+s2
Out[101]:
0 1
0 2 4
1 4 6
In [102]: df22+df21
Out[102]:
0 1
0 2 NaN
1 5 NaN
In [103]: df22+df12
Out[103]:
0 1
0 2.0 4.0
1 NaN NaN
In [104]: df23+s2
Out[104]:
0 1 2
0 4.0 6.0 NaN
1 7.0 9.0 NaN
In [130]: df21+df12
Out[130]:
0 1
0 2.0 NaN
1 NaN NaN
pandas的广播机制继承自numpy但有不一样的地方:
标量值会与DataFrame
或Series
中每个元素进行同样的计算;
Series
或一维list
或一维ndarray
会与DataFrame
的每一行进行运算,Series
在长度不足以匹配DataFrame
的行时不足部分会替换为NaN
,其他两种长度不足会报错;
DataFrame
与DataFrame
进行运算会按元素匹配,无论行列,长度不足的部分都会替换为NaN
;
二维ndarray
与DataFrame
的运算遵循numpy的广播规则,长度不足且为1的轴会被广播至同等大小;
二维list
与DataFrame
的运算不被支持。