简介
Pandas是一个用来处理表格类型数据的函数库。Pandas的官方文档:http://pandas.pydata.org/pandas-docs/stable/
1 2 import numpy as npimport pandas as pd
数据结构
主要数据结构
Series
一个Series由一个index和与之对应的一系列value组成,相当于是一个单列的表格。它的构造方式有:
1 series1=pd.Series(np.array((4 ,7 ,-5 ,3 )))
0 4
1 7
2 -5
3 3
dtype: int32
1 pd.Series([2 ,3 ,-3 ,1 ],index=['a' ,'c' ,'b' ,'d' ])
a 2
c 3
b -3
d 1
dtype: int64
1 2 dict1={'Ohio' : 35000 , 'Texas' : 71000 , 'Oregon' : 16000 , 'Utah' : 5000 } states = ['California' , 'Ohio' , 'Oregon' , 'Texas' ]
Ohio 35000
Texas 71000
Oregon 16000
Utah 5000
dtype: int64
1 pd.Series(dict1,index=states)
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64
一个Series具有以下的属性:
array([ 4, 7, -5, 3])
RangeIndex(start=0, stop=4, step=1)
1 series1.index.name='test_series'
test_series
0 4
1 7
2 -5
3 3
dtype: int32
DataFrame
DataFrame数据结构相当于一个表格。也可以理解为一个DataFrame由多个Series拼在一起,其中这些Series具有共同的index。
许多种数据类型都可以被用来构造DataFrame,包括但不限于:
二维的array
一个value为array、list或者tuple的dict
一个value为Series的dict
一个value为dict的dict
一个元素为dict或者Series的list
一个元素为list或者tuple的list
另一个DataFrame
下面为创建DataFrame的示例:
1 2 3 4 data = {'state' : ['Ohio' , 'Ohio' , 'Ohio' , 'Nevada' , 'Nevada' ], 'year' : [2000 , 2001 , 2002 , 2001 , 2002 ],'pop' : [1.5 , 1.7 , 3.6 , 2.4 , 2.9 ]}dataframe1=pd.DataFrame(data)
state
year
pop
0
Ohio
2000
1.5
1
Ohio
2001
1.7
2
Ohio
2002
3.6
3
Nevada
2001
2.4
4
Nevada
2002
2.9
1 pd.DataFrame(data, columns=['year' , 'state' , 'debt' ],index=['one' , 'two' , 'three' , 'four' , 'five' ])
year
state
debt
one
2000
Ohio
NaN
two
2001
Ohio
NaN
three
2002
Ohio
NaN
four
2001
Nevada
NaN
five
2002
Nevada
NaN
1 2 data2={'Nevada' : {2001 : 2.4 , 2002 : 2.9 }, 'Ohio' : {2000 : 1.5 , 2001 : 1.7 , 2003 : 3.6 }} pd.DataFrame(data2)
Nevada
Ohio
2001
2.4
1.7
2002
2.9
NaN
2000
NaN
1.5
2003
NaN
3.6
1 pd.DataFrame(data2,index=[2000 ,2001 ,2002 ,2004 ])
Nevada
Ohio
2000
NaN
1.5
2001
2.4
1.7
2002
2.9
NaN
2004
NaN
NaN
1 pd.DataFrame(np.random.rand(5 ,3 ))
0
1
2
0
0.860528
0.190016
0.355405
1
0.707203
0.021066
0.883826
2
0.672148
0.091125
0.984936
3
0.816604
0.672571
0.421406
4
0.327092
0.616550
0.054370
一个DataFrame具有下面的属性:
array([['Ohio', 2000, 1.5],
['Ohio', 2001, 1.7],
['Ohio', 2002, 3.6],
['Nevada', 2001, 2.4],
['Nevada', 2002, 2.9]], dtype=object)
RangeIndex(start=0, stop=5, step=1)
Index(['state', 'year', 'pop'], dtype='object')
1 2 dataframe1.index.name='test_index' dataframe1.columns.name='test_columns'
test_columns
state
year
pop
test_index
0
Ohio
2000
1.5
1
Ohio
2001
1.7
2
Ohio
2002
3.6
3
Nevada
2001
2.4
4
Nevada
2002
2.9
Panel
Panel是多个DataFrame的组合,相当于Excel中的一个.xlsx文件(其中包括多张表)。但是在目前的Pandas中已经被废弃,可能在一些旧的Pandas版本中才会有,此处不再赘述。
index属性
在上面的代码中,我们使用了index属性提取出一个series或dataframe的index,或使用columns属性提取出一个dataframe的column。这些操作得到的都是一个index类型的常量 ,也就是说index的数据无法修改!
index常量可以直接用于修改其它series或dataframe的index。同时,这个index可以像python自带的set一样使用。
Pandas中,index的类型包括但不限于:
Index:最基本的也是最通用的index类型
Int64Index:整数类型的index
MultiIndex:多重index
DatetimeIndex:使用NumPy的datetime64
类型,保存的是毫秒形式的时间戳
PeriodIndex:周期性数据构成的index
RangeIndex:index为一组等差数列组成的range,具有开始值、结束值和步长。
同时index支持下面这些方法,来构造新的index。其中,一些方法对于某些特定的index类型不适用:
append:将一个新的index附加到已有的index后面
diff:取两个index中不重复的元素
intersection:取两个index的交集
union:取两个index的并集
delete:传入一个整数,删除对应位置的元素
drop:传入一个元素的值,删除掉这个元素
insert:传入一个整数与一个值,将这个值插入到整数对应的位置
unique:输出index中不重复的元素
index也支持下面的这些运算操作:
isin:传入一个list,输出一个布尔类型的数组,表示list中的元素是否在index中
is_monotonic:如果每个元素都大于等于它的前一个,则返回True
is_unique:如果index中没有重复元素则返回True
下面为一些用法示例:
1 dataframe1.index.union(dataframe1.columns)
Index([0, 1, 2, 3, 4, 'pop', 'state', 'year'], dtype='object')
1 dataframe1.columns.is_unique
True
1 dataframe1.columns.drop('pop' )
Index(['state', 'year'], dtype='object', name='test_columns')
具有重复数据的index
在Series和DataFrame的index中,可以出现重复的元素,例如:
1 dataframe2=pd.DataFrame(np.random.randn(5 ,3 ),index=['a' ,'a' ,'b' ,'b' ,'c' ])
1 dataframe2.index.is_unique
False
0
1
2
b
1.589025
-0.504598
0.021645
b
0.629079
-0.703262
-0.759489
IO操作
读取文件
Pandas常用的从文件中读取表格数据的函数有:
1 2 pd.read_csv('filename' ) pd.read_table('filename' )
在这两个函数中,常用的参数包括:
path:文件路径,可以为本地文件路径或者URL
sep/delimiter:表格数据的分割符,可以使用正则表达式
header:文件中哪一行作为结果中的columns(列名称),默认为0。如果不使用任意一行作为columns,则这一参数应该设置为None
index_col:在最终结果中,哪些列被作为index,可以传入数字序号或者列名称
names:传入一个list,作为columns(列名称),此时header参数应该为None
skiprows:传入一个数字,代表跳过前若干行不读取,然后从接下来的行作为文件的开头进行读取;或是传入一个列表,代表跳过列表中的行
na_values:传入一个list,其中包含的元素作为NaN处理;或是传入一个dict,其中每个元素的key对应于列名,value为一个list,代表作为NaN处理的元素。默认情况下,文件中的空格或者一些特殊值都会被看作是NaN
comment:传入一个或一些字符,用于在一行的结尾将注释部分与表格内容分隔开
converters:传入一个dict,其中的元素为列名称和函数的映射,代表对某一列使用某个函数进行数据转换
nrows:代表从文件开始位置读取多少行
chunksize:传入一个整数,表示一个DataFrame中的行上限,如果原始数据中的行数大于这一上限,则最终得到的是多个DataFrame
skip_footer:代表忽略文件最后的若干行
parse_dates:是否试图将原始数据中的时间数据转换为datetime类型,默认为False。如果为True,则读取数据时会对所有的列尝试进行类型转换操作
encoding:原始数据的编码方式
此外,还有一些从其他数据来源中读取数据的函数,包括(此处不再详细赘述每个函数的具体用法):
1 2 3 4 5 pd.read_excel('filename' ,'sheetname' ) pd.read_html('filename' ) pd.read_json('filename' ) pd.read_pickle('filename' ) pd.read_sql('SQL command' , database)
写入文件
Pandas提供了将Series或者DataFrame转换为csv文件的函数:
这一函数可以传入的参数包括:
sep:指定分隔符,默认为逗号
na_rep:指定缺失数据的输出值,默认输出为空字符串
index:代表是否将index写入到文件中,默认为True
header:代表是否将columns(列名称)写入到文件中,默认为True
cols:指定写入到文件中去的列名称
如果要将文件写入Excel格式,可以使用函数:
1 frame.to_excel('filename' )
基本操作与运算
reindex
reindex函数传入一个list、tuple或者index,将其作为新的index,并将原来的数据按照新index对应起来。如果新的index中有新的元素,则它对应的值默认为NaN,也可以传入参数对其进行赋值。如果旧的index中某些元素不包含在新的index中,则新数据不包含相应的元素。
1 obj = pd.Series([4.5 , 7.2 , -5.3 , 3.6 ], index=['d' , 'b' , 'a' , 'c' ])
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
1 obj.reindex(['a' ,'b' ,'c' ,'d' ,'e' ])
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
1 obj.reindex(['a' ,'b' ,'e' ],fill_value=0 )
a -5.3
b 7.2
e 0.0
dtype: float64
1 2 obj2 = pd.Series([4.5 , 7.2 , -5.3 , 3.6 ], index=[1 ,2 ,3 ,4 ]) obj2.reindex([2 ,3 ,4 ,5 ],method='ffill' )
2 7.2
3 -5.3
4 3.6
5 3.6
dtype: float64
1 obj2.reindex([0 ,2 ,3 ,4 ,5 ],method='bfill' )
0 4.5
2 7.2
3 -5.3
4 3.6
5 NaN
dtype: float64
对于DataFrame来说,则可以同时改变它的index或者columns:
1 2 obj3=pd.DataFrame(np.arange(9 ).reshape((3 , 3 )), index=['a' , 'c' , 'd' ],columns=['Ohio' , 'Texas' , 'California' ]) obj3.reindex(['a' ,'b' ,'c' ,'d' ])
Ohio
Texas
California
a
0.0
1.0
2.0
b
NaN
NaN
NaN
c
3.0
4.0
5.0
d
6.0
7.0
8.0
1 obj3.reindex(index=['a' ,'b' ,'c' ,'d' ],columns=['Texas' ,'Utah' ,'California' ])
Texas
Utah
California
a
1.0
NaN
2.0
b
NaN
NaN
NaN
c
4.0
NaN
5.0
d
7.0
NaN
8.0
1 obj3.index=obj3.index.map (str .upper)
Ohio
Texas
California
A
0
1
2
C
3
4
5
D
6
7
8
1 obj3.rename(index=str .title,columns=str .upper)
OHIO
TEXAS
CALIFORNIA
A
0
1
2
C
3
4
5
D
6
7
8
1 obj3.rename(columns={'Ohio' : 'INDIANA' },index={'C' : 'peekaboo' })
INDIANA
Texas
California
A
0
1
2
peekaboo
3
4
5
D
6
7
8
删除操作
drop函数可以从Series或者DataFrame中删除某个index对应的行,或者DataFrame中某个column对应的列:
Ohio
Texas
California
C
3
4
5
D
6
7
8
1 obj3.drop('Texas' ,axis=1 )
Ohio
California
A
0
2
C
3
5
D
6
8
切片与索引操作
Series和DataFrame都支持索引和切片操作,同时支持使用布尔运算进行索引。
下面为Series的一些使用示例:
1 series_index=pd.Series(np.arange(4. ),index=['a' ,'b' ,'c' ,'d' ])
1.0
1.0
c 2.0
d 3.0
dtype: float64
a 0.0
b 1.0
c 2.0
dtype: float64
b 1.0
a 0.0
dtype: float64
c 2.0
b 1.0
dtype: float64
1 series_index[series_index<2 ]
a 0.0
b 1.0
dtype: float64
a 0.0
b 4.0
c 4.0
d 3.0
dtype: float64
对于DataFrame来说,它的索引与切片操作比Series要复杂一些。一些使用示例如下:
1 dataframe_index=pd.DataFrame(np.arange(16 ).reshape((4 , 4 )),index=['Ohio' , 'Colorado' , 'Utah' , 'New York' ], columns=['one' , 'two' , 'three' , 'four' ])
Ohio 1
Colorado 5
Utah 9
New York 13
Name: two, dtype: int32
1 2 dataframe_index[['three' ,'one' ]]
three
one
Ohio
2
0
Colorado
6
4
Utah
10
8
New York
14
12
one
two
three
four
Ohio
0
1
2
3
Colorado
4
5
6
7
1 dataframe_index.take([2 ,3 ,1 ,1 ])
one
two
three
four
Utah
8
9
10
11
New York
12
13
14
15
Colorado
4
5
6
7
Colorado
4
5
6
7
1 dataframe_index[dataframe_index<5 ]
one
two
three
four
Ohio
0.0
1.0
2.0
3.0
Colorado
4.0
NaN
NaN
NaN
Utah
NaN
NaN
NaN
NaN
New York
NaN
NaN
NaN
NaN
1 dataframe_index[dataframe_index['three' ]>5 ]
one
two
three
four
Colorado
4
5
6
7
Utah
8
9
10
11
New York
12
13
14
15
1 dataframe_index['five' ]=[3 ,4 ,5 ,6 ]
one
two
three
four
five
Ohio
0
1
2
3
3
Colorado
4
5
6
7
4
Utah
8
9
10
11
5
New York
12
13
14
15
6
除了上述这些操作,pandas还提供了loc
和iloc
两种运算符进行索引操作,loc
是使用index和columns中的内容进行索引,而iloc
则是使用整数。同样,也可以使用at
和iat
两个运算符,索引某行和某列对应的那个元素。这种索引方式的含义清晰,不会让人混淆,因此在索引操作时最好使用这种办法。
下面是一些使用示例:
1 dataframe_index.loc['Ohio' :'Utah' ,['one' ,'two' ]]
one
two
Ohio
0
1
Colorado
4
5
Utah
8
9
1 dataframe_index.loc[:,['one' ,'two' ]]
one
two
Ohio
0
1
Colorado
4
5
Utah
8
9
New York
12
13
1 dataframe_index.loc[['New York' ,'Utah' ]]
one
two
three
four
five
New York
12
13
14
15
6
Utah
8
9
10
11
5
1 dataframe_index.iloc[2 :4 ,1 :3 ]
two
three
Utah
9
10
New York
13
14
1 dataframe_index.iloc[[2 ,3 ],[0 ,1 ]]
one
two
Utah
8
9
New York
12
13
1 dataframe_index.at['Utah' ,'one' ]
8
1 dataframe_index.iat[1 ,1 ]
5
数学运算
Series和DataFrame支持一些数学运算,包括:
add()
,或使用运算符+
sub()
,或使用运算符-
mul()
,或使用运算符*
div()
,或使用运算符/
以加法为例,对两个index不相同的Series相加时,最后得到的index是两个index的并集。默认情况下,运算结果满足以下规律:如果是两个index里面都有的key,则它对应的结果是这个key在两个Series里对应的value之和;如果某些key只出现在其中一个index里面,则相加后对应的value值为空。
DataFrame也满足上述的规则,并且在考虑index的基础上,也要考虑columns。
下面是一些使用示例:
1 2 dataframe_math1=pd.DataFrame(np.arange(12. ).reshape((3 , 4 )), columns=list ('abcd' )) dataframe_math2=pd.DataFrame(np.arange(20. ).reshape((4 , 5 )), columns=list ('abcde' ))
1 dataframe_math1+dataframe_math2
a
b
c
d
e
0
0.0
2.0
4.0
6.0
NaN
1
9.0
11.0
13.0
15.0
NaN
2
18.0
20.0
22.0
24.0
NaN
3
NaN
NaN
NaN
NaN
NaN
1 dataframe_math1.add(dataframe_math2,fill_value=0 )
a
b
c
d
e
0
0.0
2.0
4.0
6.0
4.0
1
9.0
11.0
13.0
15.0
9.0
2
18.0
20.0
22.0
24.0
14.0
3
15.0
16.0
17.0
18.0
19.0
如果是一个DataFrame和Series进行运算,那么默认会把Series的元素按行复制进行扩展,然后参与运算。如果Series的index和DataFrame的columns不是完全相同,也可以进行运算,运算规则与两个DataFrame的运算规则类似。例如:
1 2 series_math1=dataframe_math1.iloc[0 ] dataframe_math1-series_math1
a
b
c
d
0
0.0
0.0
0.0
0.0
1
4.0
4.0
4.0
4.0
2
8.0
8.0
8.0
8.0
1 2 series_math2=series_math1.reindex(['a' ,'b' ,'c' ,'e' ]) dataframe_math1-series_math2
a
b
c
d
e
0
0.0
0.0
0.0
NaN
NaN
1
4.0
4.0
4.0
NaN
NaN
2
8.0
8.0
8.0
NaN
NaN
1 2 series_math3=dataframe_math1['d' ] dataframe_math1.subtract(series_math3,axis=0 )
a
b
c
d
0
-3.0
-2.0
-1.0
0.0
1
-3.0
-2.0
-1.0
0.0
2
-3.0
-2.0
-1.0
0.0
函数与映射
Numpy中的ufunc(即一元函数)也可以使用pandas中的series和dataframe类型的变量作为输入参数。下面为一些使用示例:
1 2 dataframe_func = pd.DataFrame(np.random.randn(4 , 3 ), columns=list ('bde' ),index=['Utah' , 'Ohio' , 'Texas' , 'Oregon' ]) dataframe_func
b
d
e
Utah
0.452034
-1.067267
2.235212
Ohio
-1.205085
0.899914
-1.097603
Texas
-1.553192
-0.820639
0.025214
Oregon
-0.047253
1.092414
-0.302945
b
d
e
Utah
1.571506
0.343947
9.348460
Ohio
0.299666
2.459391
0.333670
Texas
0.211572
0.440151
1.025534
Oregon
0.953846
2.981464
0.738640
同时也可以自己定义函数,然后使用apply
函数作用于每一行或者每一列。如果函数返回一个数值,那么最后生成一个Series;如果函数返回一个矢量值,最后生成一个DataFrame。
1 f1=lambda x:x.max ()-x.min ()
1 dataframe_func.apply(f1)
b 2.005226
d 2.159681
e 3.332815
dtype: float64
1 dataframe_func.apply(f1,axis=1 )
Utah 3.302478
Ohio 2.104999
Texas 1.578405
Oregon 1.395360
dtype: float64
备注:在Pandas的一些函数中,如果传入axis=……
参数,则代表这一函数操作在这个传入的维度上面进行。假设有一个DataFrame,它的元素可以用\(a_{ij}\) 来表示,当我们在使用sum()
函数时传入axis=1
,那么最终得到的结果便可以用数学公式表示为\(\sum_{j=1}^{n}a_{ij}\) ,也就是说这个操作是在维度\(j\) 上进行的,也就是水平方向。
applymap
方法可以让函数作用于每一个元素:
1 2 f2=lambda x: '%.2f' %x dataframe_func.applymap(f2)
b
d
e
Utah
0.45
-1.07
2.24
Ohio
-1.21
0.90
-1.10
Texas
-1.55
-0.82
0.03
Oregon
-0.05
1.09
-0.30
排序
Series或DataFrame的index和columns可以使用sort_index()
函数对其进行排序,使得行或列按照index排序后的顺序进行排列。sort_index()
函数生成的是原始数据的一个副本。
示例:
1 2 series_sort=pd.Series(range (4 ), index=['d' , 'a' , 'b' , 'c' ]) series_sort.sort_index()
a 1
b 2
c 3
d 0
dtype: int64
1 dataframe_sort=pd.DataFrame(np.arange(8 ).reshape((2 , 4 )), index=['three' , 'one' ], columns=['d' , 'a' , 'b' , 'c' ])
1 dataframe_sort.sort_index()
d
a
b
c
one
4
5
6
7
three
0
1
2
3
1 dataframe_sort.sort_index(axis=1 )
a
b
c
d
three
1
2
3
0
one
5
6
7
4
1 dataframe_sort.sort_index(axis=1 ,ascending=False )
d
c
b
a
three
0
3
2
1
one
4
7
6
5
如果想对Series或者DataFrame按照元素的大小顺序进行排序,可以用sort_values()
方法,其中NaN值会自动排在最后:
1 dataframe_sort2=pd.DataFrame({'b' : [4 , 7 , -3 , 2 ], 'a' : [0 , 1 , 0 , 1 ]})
1 dataframe_sort2.sort_values(by='b' )
b
a
2
-3
0
3
2
1
0
4
0
1
7
1
1 dataframe_sort2.sort_values(by=['a' ,'b' ])
b
a
2
-3
0
0
4
0
3
2
1
1
7
1
使用rank()
方法,可以生成Series或DataFrame中的元素的排列次序,类似于NumPy的argsort()函数。
rank()
在处理重复值的时候,有如下几种方法:
average:生成重复值对应顺序的平均值。例如两个重复值分别排1和2,则它们的rank都为1.5
min:重复值使用最小的那个rank
max:重复值使用最大的那个rank
first:使用重复值中第一个出现的那个对应的rank
b
a
0
3.0
1.5
1
4.0
3.5
2
1.0
1.5
3
2.0
3.5
1 dataframe_sort2.rank(axis=1 )
b
a
0
2.0
1.0
1
2.0
1.0
2
1.0
2.0
3
2.0
1.0
1 dataframe_sort2.rank(method='max' ,ascending=False )
b
a
0
2.0
4.0
1
1.0
2.0
2
4.0
4.0
3
3.0
2.0
统计函数
Pandas支持对Series和DataFrame中的数据做一些数学统计,常用的统计函数包括:
count:统计非NaN元素的数目
describe:自动统计dataframe中每一列的数据数目,平均值,标准差,最小值,25%,50%,75%,100%分位数,可以用于分析数据的大致统计规律
min、max:统计最小或最大值
argmin、argmax:统计最小或最大值出现的位置,返回对应的序号
idxmin、idxmax:统计最小或最大值出现的位置,返回对应的index值
quantile:统计某个百分位数(需要传入一个0到1中间的数字)
sum:统计所有元素的和
mean:统计所有元素的平均数
median:统计所有元素的中位数
mad:统计相较于平均值的绝对偏差的平均值
var:统计方差
std:统计标准差
skew:统计偏度,表示随机变量与中心分布的不对称程度\((μ^3/σ^3)\) ,右偏为正,左偏为负
kurt:统计峰度,表征概率密度分布曲线在平均值处峰值高低的特征数\((μ^4/σ^4)\) 。以正态分布为界,如果比正态分布陡,峰度大于0,否则小于0
cumsum:计算累积和(即保留计算总和时中间每一步的结果)
cummin、cummax:计算累积最小值或最大值
cumprod:计算累积乘积
diff:计算一阶算数偏差(即拿第二个值减第一个,第三个值减第二个,以此类推)
pct_change:计算百分数改变
在统计函数中,可以使用的一些参数包括:
axis:指定统计函数在哪个维度上计算,0为行,1为列(即0是按照竖直方向,1是按照水平方向)
skipna:是否跳过NaN,默认为True
level:如果使用多重index,则对每一个层级的结果进行分组
下面为一些使用示例:
1 2 dataframe_stat=pd.DataFrame(np.random.rand(5 ,5 ),columns=['a' ,'b' ,'c' ,'d' ,'e' ]) dataframe_stat
a
b
c
d
e
0
0.925587
0.285093
0.016950
0.140965
0.179401
1
0.213783
0.146496
0.816971
0.065923
0.067685
2
0.615921
0.717184
0.375118
0.233150
0.188625
3
0.469468
0.960874
0.769445
0.503390
0.928483
4
0.480754
0.340058
0.424418
0.566608
0.810999
1 dataframe_stat.pct_change()
a
b
c
d
e
0
NaN
NaN
NaN
NaN
NaN
1
-0.769030
-0.486148
47.199252
-0.532347
-0.622717
2
1.881058
3.895602
-0.540843
2.536707
1.786814
3
-0.237778
0.339787
1.051211
1.159082
3.922365
4
0.024039
-0.646095
-0.448410
0.125585
-0.126533
1 dataframe_stat.describe()
a
b
c
d
e
count
5.000000
5.000000
5.000000
5.000000
5.000000
mean
0.541102
0.489941
0.480580
0.302007
0.435039
std
0.259489
0.337565
0.326279
0.221912
0.401825
min
0.213783
0.146496
0.016950
0.065923
0.067685
25%
0.469468
0.285093
0.375118
0.140965
0.179401
50%
0.480754
0.340058
0.424418
0.233150
0.188625
75%
0.615921
0.717184
0.769445
0.503390
0.810999
max
0.925587
0.960874
0.816971
0.566608
0.928483
1 dataframe_stat.min (axis=1 )
0 0.016950
1 0.065923
2 0.188625
3 0.469468
4 0.340058
dtype: float64
Pandas也提供了协方差和相关系数的计算,例如:
a
b
c
d
e
a
1.000000
0.074114
-0.925876
-0.087650
-0.130717
b
0.074114
1.000000
0.226825
0.512625
0.550285
c
-0.925876
0.226825
1.000000
0.158210
0.271455
d
-0.087650
0.512625
0.158210
1.000000
0.963646
e
-0.130717
0.550285
0.271455
0.963646
1.000000
a
b
c
d
e
a
0.067334
0.006492
-0.078390
-0.005047
-0.013630
b
0.006492
0.113950
0.024983
0.038401
0.074642
c
-0.078390
0.024983
0.106458
0.011455
0.035590
d
-0.005047
0.038401
0.011455
0.049245
0.085928
e
-0.013630
0.074642
0.035590
0.085928
0.161463
1 dataframe_stat['a' ].cov(dataframe_stat['c' ])
-0.07838993925634331
此外,还有一些用于统计Series中数据数目以及查找数据的函数,下面为一些使用示例:
1 2 series_stat=pd.Series([1 ,2 ,3 ,1 ,1 ,1 ,1 ,2 ,4 ,5 ,5 ]) series_stat
0 1
1 2
2 3
3 1
4 1
5 1
6 1
7 2
8 4
9 5
10 5
dtype: int64
1 series_stat.value_counts()
1 5
5 2
2 2
4 1
3 1
dtype: int64
array([1, 2, 3, 4, 5], dtype=int64)
1 series_stat.isin([3 ,4 ,6 ])
0 False
1 False
2 True
3 False
4 False
5 False
6 False
7 False
8 True
9 False
10 False
dtype: bool
1 pd.DataFrame([series_stat,series_stat,series_stat]).apply(pd.value_counts)
0
1
2
3
4
5
6
7
8
9
10
1
3.0
NaN
NaN
3.0
3.0
3.0
3.0
NaN
NaN
NaN
NaN
2
NaN
3.0
NaN
NaN
NaN
NaN
NaN
3.0
NaN
NaN
NaN
3
NaN
NaN
3.0
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
4
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
3.0
NaN
NaN
5
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
3.0
3.0
数据清洗
处理丢失数据
在Pandas中,可能会遇到Series或者DataFrame中存在丢失数据的情况。对于如何处理丢失数据,Pandas提供了一些相关的函数。
1 2 3 4 5 6 7 dataframe_nan=pd.DataFrame( {'Nevada' : {2001 :2.4 , 2002 :2.9 , 2003 :3.3 }, 'Ohio' : {2000 :1.5 , 2001 :1.7 , 2003 :3.6 }, 'New York' :{2003 :3.5 , 2004 :5.7 }, 'Denver' :{2000 :0.5 , 2001 :1.1 , 2002 :2.1 , 2003 :1.5 , 2004 :0.9 }}, index=[2000 ,2001 ,2002 ,2003 ,2004 ,2005 ]) dataframe_nan
Nevada
Ohio
New York
Denver
2000
NaN
1.5
NaN
0.5
2001
2.4
1.7
NaN
1.1
2002
2.9
NaN
NaN
2.1
2003
3.3
3.6
3.5
1.5
2004
NaN
NaN
5.7
0.9
2005
NaN
NaN
NaN
NaN
要判断某个位置是否是NaN,可以使用isnull()
函数,这一函数返回一个bool类型的Series或者DataFrame,指示每个位置上是否为NaN。
dropna()
函数可以将丢失的数据删除掉。对于Series来说,丢失的数据会被直接删除掉;而对于DataFrame来说,默认操作是只要一行内有一个NaN就把这一行全部删除。下面是一些程序示例:
Nevada
Ohio
New York
Denver
2003
3.3
3.6
3.5
1.5
1 dataframe_nan.dropna(how='all' )
Nevada
Ohio
New York
Denver
2000
NaN
1.5
NaN
0.5
2001
2.4
1.7
NaN
1.1
2002
2.9
NaN
NaN
2.1
2003
3.3
3.6
3.5
1.5
2004
NaN
NaN
5.7
0.9
1 dataframe_nan.dropna(axis=1 , thresh=3 )
Nevada
Ohio
Denver
2000
NaN
1.5
0.5
2001
2.4
1.7
1.1
2002
2.9
NaN
2.1
2003
3.3
3.6
1.5
2004
NaN
NaN
0.9
2005
NaN
NaN
NaN
如果要删除指定列中包含NaN的行或列,可以传入subset参数来进行设定。例如:
1 dataframe_nan.dropna(subset=['Ohio' ])
2000
NaN
1.5
NaN
0.5
2001
2.4
1.7
NaN
1.1
2003
3.3
3.6
3.5
1.5
要对缺失的数据进行填补,可以使用fillna
函数。这一函数支持传入不同类型的参数,从而进行不同方法的填补。函数的返回值是一个新的变量,不改变原变量,如果要对原变量直接修改可以传入inplace=True
参数。
1 dataframe_nan.fillna(dataframe_nan.mean())
Nevada
Ohio
New York
Denver
2000
2.866667
1.500000
4.6
0.50
2001
2.400000
1.700000
4.6
1.10
2002
2.900000
2.266667
4.6
2.10
2003
3.300000
3.600000
3.5
1.50
2004
2.866667
2.266667
5.7
0.90
2005
2.866667
2.266667
4.6
1.22
Nevada
Ohio
New York
Denver
2000
0.0
1.5
0.0
0.5
2001
2.4
1.7
0.0
1.1
2002
2.9
0.0
0.0
2.1
2003
3.3
3.6
3.5
1.5
2004
0.0
0.0
5.7
0.9
2005
0.0
0.0
0.0
0.0
1 dataframe_nan.fillna(method='ffill' ,limit=1 )
Nevada
Ohio
New York
Denver
2000
NaN
1.5
NaN
0.5
2001
2.4
1.7
NaN
1.1
2002
2.9
1.7
NaN
2.1
2003
3.3
3.6
3.5
1.5
2004
3.3
3.6
5.7
0.9
2005
NaN
NaN
5.7
0.9
除去重复数据
drop_duplicates()
函数可以删除掉一个series或dataframe中的重复行。默认条件下,drop_duplicates()
函数只会删除一行的所有元素都相同的多余行。如果想基于某些特定的行作为判断标准,需要传入一个以列名称构成的list作为参数。同时,默认条件下函数会保留第一个发现的行,如果想取最后一个发现的行,需要传入keep='last'
参数。
下面是一些使用示例:
1 dataframe_duplicate=pd.DataFrame({'k1' : ['one' ] * 3 + ['two' ] * 4 , 'k2' : [1 , 1 , 2 , 3 , 3 , 4 , 4 ]})
k1
k2
0
one
1
1
one
1
2
one
2
3
two
3
4
two
3
5
two
4
6
two
4
1 dataframe_duplicate.duplicated()
0 False
1 True
2 False
3 False
4 True
5 False
6 True
dtype: bool
1 dataframe_duplicate.drop_duplicates()
k1
k2
0
one
1
2
one
2
3
two
3
5
two
4
1 dataframe_duplicate.drop_duplicates(['k1' ])
1 dataframe_duplicate.drop_duplicates(['k1' ],keep='last' )
函数与映射
map()
函数支持传入一个函数或者dict变量,从而对一个Series中的所有数据做映射,得到转换后的数据。注意这一操作不能对DataFrame进行。例如:
1 2 dataframe_map = pd.DataFrame({'food' : ['bacon' , 'pulled pork' , 'bacon' , 'Pastrami' ,'corned beef' , 'Bacon' , 'pastrami' , 'honey ham' , 'nova lox' ],'ounces' : [4 , 3 , 12 , 6 , 7.5 , 8 , 3 , 5 , 6 ]}) meat_to_animal = {'bacon' : 'pig' ,'pulled pork' : 'pig' ,'pastrami' : 'cow' ,'corned beef' : 'cow' ,'honey ham' : 'pig' ,'nova lox' : 'salmon' }
food
ounces
0
bacon
4.0
1
pulled pork
3.0
2
bacon
12.0
3
Pastrami
6.0
4
corned beef
7.5
5
Bacon
8.0
6
pastrami
3.0
7
honey ham
5.0
8
nova lox
6.0
1 dataframe_map['animal' ]=dataframe_map['food' ].map (str .lower).map (meat_to_animal)
food
ounces
animal
0
bacon
4.0
pig
1
pulled pork
3.0
pig
2
bacon
12.0
pig
3
Pastrami
6.0
cow
4
corned beef
7.5
cow
5
Bacon
8.0
pig
6
pastrami
3.0
cow
7
honey ham
5.0
pig
8
nova lox
6.0
salmon
数据替换
使用replace
函数,可以对Series或者DataFrame中的某些值进行替换。replace
函数可以传入两个参数,第一个代表需要替换的值,可以是一个值,也可以是一个list;第二个代表要替换成的值,可以是一个值,也可以是一个与第一个参数大小相同的list。也或者是只传入一个dict作为参数。例如:
1 dataframe_replace=dataframe_map
food
ounces
animal
0
bacon
4.0
pig
1
pulled pork
3.0
pig
2
bacon
12.0
pig
3
Pastrami
6.0
cow
4
corned beef
7.5
cow
5
Bacon
8.0
pig
6
pastrami
3.0
cow
7
honey ham
5.0
pig
8
nova lox
6.0
salmon
1 dataframe_replace.replace('pig' ,'PIG' )
food
ounces
animal
0
bacon
4.0
PIG
1
pulled pork
3.0
PIG
2
bacon
12.0
PIG
3
Pastrami
6.0
cow
4
corned beef
7.5
cow
5
Bacon
8.0
PIG
6
pastrami
3.0
cow
7
honey ham
5.0
PIG
8
nova lox
6.0
salmon
1 dataframe_replace.replace(['pig' ,'bacon' ],[np.nan,'Bacon' ])
food
ounces
animal
0
Bacon
4.0
NaN
1
pulled pork
3.0
NaN
2
Bacon
12.0
NaN
3
Pastrami
6.0
cow
4
corned beef
7.5
cow
5
Bacon
8.0
NaN
6
pastrami
3.0
cow
7
honey ham
5.0
NaN
8
nova lox
6.0
salmon
1 dataframe_replace.replace({4.0 :-4.0 ,7.5 :-7.5 })
food
ounces
animal
0
bacon
-4.0
pig
1
pulled pork
3.0
pig
2
bacon
12.0
pig
3
Pastrami
6.0
cow
4
corned beef
-7.5
cow
5
Bacon
8.0
pig
6
pastrami
3.0
cow
7
honey ham
5.0
pig
8
nova lox
6.0
salmon
频数统计
Pandas中的cut()
函数可以对一个list中的数据按照给定的区间进行分类,从而进一步统计它们的频数。下面为一些使用示例:
1 2 3 ages=[20 , 22 , 25 , 27 , 21 , 23 , 37 , 31 , 61 , 45 , 41 , 32 ] bins=[18 ,25 ,35 ,60 ,100 ] cats=pd.cut(ages,bins)
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
(18, 25] 5
(35, 60] 3
(25, 35] 3
(60, 100] 1
dtype: int64
1 pd.cut(ages,bins,right=False )
[[18, 25), [18, 25), [25, 35), [25, 35), [18, 25), ..., [25, 35), [60, 100), [35, 60), [35, 60), [25, 35)]
Length: 12
Categories (4, interval[int64]): [[18, 25) < [25, 35) < [35, 60) < [60, 100)]
1 2 group_names = ['Youth' , 'YoungAdult' , 'MiddleAged' , 'Senior' ] pd.cut(ages,bins,labels=group_names)
[Youth, Youth, Youth, YoungAdult, Youth, ..., YoungAdult, Senior, MiddleAged, MiddleAged, YoungAdult]
Length: 12
Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]
1 pd.cut(ages,4 ,precision=2 )
[(19.96, 30.25], (19.96, 30.25], (19.96, 30.25], (19.96, 30.25], (19.96, 30.25], ..., (30.25, 40.5], (50.75, 61.0], (40.5, 50.75], (40.5, 50.75], (30.25, 40.5]]
Length: 12
Categories (4, interval[float64]): [(19.96, 30.25] < (30.25, 40.5] < (40.5, 50.75] < (50.75, 61.0]]
另一个功能相近的函数为qcut()
。这个函数的用法有两种:第一种是传入一个整数,代表将所有元素均分为若干份,然后根据均分结果得到区间范围;第二种是传入一个list,list中的元素为0到1递增的数字,每个数字代表在该分位数处作为一个区间的起点/终点。用法如下:
1 data_qcut=np.random.randn(1000 )
[(0.787, 2.964], (-3.3779999999999997, -0.802], (-0.802, -0.226], (-0.802, -0.226], (-3.3779999999999997, -0.802], ..., (-0.802, -0.226], (-0.226, 0.236], (-0.226, 0.236], (0.236, 0.787], (-0.802, -0.226]]
Length: 1000
Categories (5, interval[float64]): [(-3.3779999999999997, -0.802] < (-0.802, -0.226] < (-0.226, 0.236] < (0.236, 0.787] < (0.787, 2.964]]
1 pd.value_counts(pd.qcut(data_qcut,5 ))
(0.787, 2.964] 200
(0.236, 0.787] 200
(-0.226, 0.236] 200
(-0.802, -0.226] 200
(-3.3779999999999997, -0.802] 200
dtype: int64
1 pd.qcut(data_qcut,[0 ,0.1 ,0.5 ,0.9 ,1 ])
[(1.267, 2.964], (-1.179, -0.0053], (-1.179, -0.0053], (-1.179, -0.0053], (-1.179, -0.0053], ..., (-1.179, -0.0053], (-1.179, -0.0053], (-0.0053, 1.267], (-0.0053, 1.267], (-1.179, -0.0053]]
Length: 1000
Categories (4, interval[float64]): [(-3.3779999999999997, -1.179] < (-1.179, -0.0053] < (-0.0053, 1.267] < (1.267, 2.964]]
1 pd.value_counts(pd.qcut(data_qcut,[0 ,0.1 ,0.5 ,0.9 ,1 ]))
(-0.0053, 1.267] 400
(-1.179, -0.0053] 400
(1.267, 2.964] 100
(-3.3779999999999997, -1.179] 100
dtype: int64
Dummy变量
在Series或DataFrame中,某些列可能为类别型的变量。而在机器学习等任务中,有时可能需要将其转换为0和1编码的二值变量。Pandas的get_dummies()
函数便可以完成这一功能。
get_dummies
需要将一个Series或者DataFrame作为输入。假设某一列中的数据出现了k种不重复的元素,在这一操作之后会生成出k列。其中每一列都代表k种类别中的某一个,全部用0或1填充,某一列为1则代表这个类别是原始列中这一行的数据。例如:
1 dataframe_dummy=pd.DataFrame({'key' : ['b' , 'b' , 'a' , 'c' , 'a' , 'b' ],'data1' : range (6 ),'key2' : ['b' , 'b' , 'a' , 'c' , 'a' , 'd' ]})
key
data1
key2
0
b
0
b
1
b
1
b
2
a
2
a
3
c
3
c
4
a
4
a
5
b
5
d
1 pd.get_dummies(dataframe_dummy)
data1
key_a
key_b
key_c
key2_a
key2_b
key2_c
key2_d
0
0
0
1
0
0
1
0
0
1
1
0
1
0
0
1
0
0
2
2
1
0
0
1
0
0
0
3
3
0
0
1
0
0
1
0
4
4
1
0
0
1
0
0
0
5
5
0
1
0
0
0
0
1
1 pd.get_dummies(dataframe_dummy['key' ])
a
b
c
0
0
1
0
1
0
1
0
2
1
0
0
3
0
0
1
4
1
0
0
5
0
1
0
1 pd.get_dummies(dataframe_dummy['key' ],prefix='Key' )
Key_a
Key_b
Key_c
0
0
1
0
1
0
1
0
2
1
0
0
3
0
0
1
4
1
0
0
5
0
1
0
需要注意的是,Series中的整数会自动按照这种方式编码,但是DataFrame中的整数不会。
字符串的处理
Pandas中提供了一些矢量化的字符串函数,可以用来批量处理Series或者DataFrame中的字符串。包括:
cat:将字符串拼接起来,并可以使用分隔符
contains:判断字符串是否含有特定的子串
count:判断特定的子串出现的次数
endswith/startswith:是否以某个特定的子串作为开头/结尾
findall:找到子串或者正则表达式出现过的所有地方
get:对字符串做索引
join:使用分隔符将字符串拼接起来
len:计算字符串长度
lower/upper:转换为大写/小写
match:使用正则表达式进行匹配,找到匹配的部分
pad:在字符串的左侧/右侧/双侧(等价于center函数)添加空格
repeat:将字符串重复若干次
replace:将某个子串或者正则表达式匹配到的部分替换为其他字符串
slice:将字符串进行分割
split:根据某个分隔符或者正则表达式对字符串进行分割
strip/rstrip/lstrip:切掉空格,然后替换成换行
这些用法与Python自带的字符串处理函数或是正则表达式处理函数类似,此处不再赘述。
多层index
Pandas中实现了一种叫做MultiIndex的类,允许Series和DataFrame有多层的index。
下面是Series中使用多层index的一些相关操作:
1 series_multiIndex=pd.Series(np.random.randn(10 ),index=[['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'd' , 'd' ],[1 , 2 , 3 , 1 , 2 , 3 , 1 , 2 , 2 , 3 ]])
a 1 2.862886
2 1.973711
3 1.367350
b 1 1.245817
2 1.270334
3 0.872359
c 1 0.651468
2 -0.454727
d 2 1.249058
3 0.591254
dtype: float64
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 2),
('b', 3),
('c', 1),
('c', 2),
('d', 2),
('d', 3)],
)
MultiIndex可以通过传入嵌套数组来创建:
1 pd.MultiIndex.from_arrays([['Ohio' , 'Ohio' , 'Colorado' ], ['Green' , 'Red' , 'Green' ]],names=['state' ,'color' ])
MultiIndex([( 'Ohio', 'Green'),
( 'Ohio', 'Red'),
('Colorado', 'Green')],
names=['state', 'color'])
对具有多重index的Series或者DataFrame,在做索引操作时需要同时传入内外层的索引元素。因此,这与单层index的索引操作有些不同,下面以例子进行说明:
1 1.245817
2 1.270334
3 0.872359
dtype: float64
1 series_multiIndex[('b' ,1 )]
1.2458169817277376
1 series_multiIndex[['b' ,'d' ]]
b 1 1.245817
2 1.270334
3 0.872359
d 2 1.249058
3 0.591254
dtype: float64
a 2.862886
b 1.245817
c 0.651468
dtype: float64
注意:在MultiIndex中使用整数序号进行索引时会比较容易混淆。其基本规则可以大致描述为,多重index在使用整数索引时,会优先匹配index中是否包含这个整数,如果没有则将其作为序号进行索引。下面进行详细的说明:
1.973710915404737
1 2 series_multiIndex2=pd.Series(np.random.randn(10 ),index=[[1 , 2 , 3 , 1 , 2 , 3 , 1 , 2 , 2 , 3 ],['a' , 'a' , 'a' , 'b' , 'b' , 'b' , 'c' , 'c' , 'd' , 'd' ]]) series_multiIndex2[1 ]
a -0.041453
b -0.329131
c -0.776732
dtype: float64
0.7369307651244501
对于使用两层index的Series来说,如果要解除多层index,可以使用unstack()
函数;它相应的反操作为stack()
。stack
操作的实质是将某个columns“旋转”至index,而unstack
操作则是将某个index“旋转”至columns。
此处有一些简单的示例,在下面的内容中还会对这一操作进行进一步的分析。
1 series_multiIndex.unstack()
1
2
3
a
2.862886
1.973711
1.367350
b
1.245817
1.270334
0.872359
c
0.651468
-0.454727
NaN
d
NaN
1.249058
0.591254
1 series_multiIndex.unstack(level=0 )
a
b
c
d
1
2.862886
1.245817
0.651468
NaN
2
1.973711
1.270334
-0.454727
1.249058
3
1.367350
0.872359
NaN
0.591254
1 series_multiIndex.unstack(level=0 ).stack()
1 a 2.862886
b 1.245817
c 0.651468
2 a 1.973711
b 1.270334
c -0.454727
d 1.249058
3 a 1.367350
b 0.872359
d 0.591254
dtype: float64
如果要改变层级顺序,可以使用swaplevel函数,在交换前后,Series中的元素顺序保持不变:
1 series_multiIndex.swaplevel(0 ,1 )
1 a 2.862886
2 a 1.973711
3 a 1.367350
1 b 1.245817
2 b 1.270334
3 b 0.872359
1 c 0.651468
2 c -0.454727
d 1.249058
3 d 0.591254
dtype: float64
在部分统计函数中,可以添加level参数,这样便可以根据指定的level做统计:
1 series_multiIndex.sum (level=1 )
1 4.760171
2 4.038376
3 2.830964
dtype: float64
如果要删除多重index中的某一层,可以调用droplevel()
函数。
1 series_multiIndex.droplevel(0 )
1 2 3 4 5 6 7 8 9 10 11 1 1.210290 2 1.367135 3 -0.072713 1 -0.122782 2 -0.359306 3 -0.515809 1 0.420951 2 -0.667417 2 -1.967170 3 0.193437 dtype: float64
对于DataFrame来说,index和columns都可以使用MultiIndex。下面为一些使用示例:
1 dataframe_multiIndex= pd.DataFrame(np.arange(12 ).reshape((4 , 3 )),index=[['a' , 'a' , 'b' , 'b' ], [1 , 2 , 1 , 2 ]],columns=[['Ohio' , 'Ohio' , 'Colorado' ],['Green' , 'Red' , 'Green' ]])
Ohio
Colorado
Green
Red
Green
a
1
0
1
2
2
3
4
5
b
1
6
7
8
2
9
10
11
在DataFrame中,可以使用set_index
函数指定某个或某些列来作为index;它的反操作是reset_index
,可以将某个或某些index转化为列插入进DataFrame中去。下面是一些实例:
1 dataframe_multiIndex2=pd.DataFrame({'a' : range (7 ), 'b' : range (7 , 0 , -1 ),'c' : ['one' , 'one' , 'one' , 'two' , 'two' , 'two' , 'two' ],'d' : [0 , 1 , 2 , 0 , 1 , 2 , 3 ]},index=['a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ])
a
b
c
d
a
0
7
one
0
b
1
6
one
1
c
2
5
one
2
d
3
4
two
0
e
4
3
two
1
f
5
2
two
2
g
6
1
two
3
1 dataframe_multiIndex2.set_index(['c' ,'d' ])
a
b
c
d
one
0
0
7
1
1
6
2
2
5
two
0
3
4
1
4
3
2
5
2
3
6
1
1 dataframe_multiIndex2.set_index(['d' ,'c' ],drop=False )
a
b
c
d
d
c
0
one
0
7
one
0
1
one
1
6
one
1
2
one
2
5
one
2
0
two
3
4
two
0
1
two
4
3
two
1
2
two
5
2
two
2
3
two
6
1
two
3
1 dataframe_multiIndex.reset_index([0 ,1 ])
level_0
level_1
Ohio
Colorado
Green
Red
Green
0
a
1
0
1
2
1
a
2
3
4
5
2
b
1
6
7
8
3
b
2
9
10
11
数据的重构与组合
按列合并
merge函数可以将两个DataFrame按列合并起来,这一函数要求在两个DataFrame中各自选择一列,然后按照这一列中元素的对应关系,将两个DataFrame合并为一个。默认情况下,函数会自己选择名称相同的列。
默认情况下,只有当某个元素在两个DataFrame里面选中的列内都出现时(即交集),最终合并得到的DataFrame中才会包含有相应元素;只出现在其中一个DataFrame中的元素会被舍去。
merge()
函数支持传入下面的可选参数:
left:以左侧的DataFrame为基准进行合并
right:以右侧的DataFrame为基准进行合并
how:可以选择'inner','outer','left'和'right'四种模式。四种模式的意义如下:
inner:左右两侧元素保留交集部分(默认操作)
outer:左右两侧元素全部保留
left:保留仅出现在左边的元素,舍去仅出现在右边的元素
right:保留仅出现在右边的元素,舍去仅出现在左边的元素
on:指定参与合并操作的列名
left_on:指定左侧DataFrame中参与合并操作的列名
right_on:指定右侧DataFrame中参与合并操作的列名
left_index:是否使用左侧DataFrame的index参与合并,默认为False
right_index:是否使用右侧DataFrame的index参与合并,默认为False
sort:是否按照参与合并的元素对DataFrame进行排序,默认为True。如果要处理大表格时可以使用False来加快速度
suffixes:传入一个二元的tuple用于区分数据来自于哪一个DataFrame,当出现重名的columns时则会自动在这些columns后面加上后缀。默认值为('_x'和'_y')
copy:是否生成原始数据的副本,默认为True
下面为一些使用示例:
1 2 3 dataframe_merge1=pd.DataFrame({'value' : ['b' , 'b' , 'a' , 'c' , 'a' , 'a' , 'b' ],'data1' : range (7 )}) dataframe_merge2=pd.DataFrame({'value' : ['a' , 'b' , 'd' ],'data2' : range (3 )}) pd.merge(dataframe_merge1,dataframe_merge2)
value
data1
data2
0
b
0
1
1
b
1
1
2
b
6
1
3
a
2
0
4
a
4
0
5
a
5
0
1 pd.merge(dataframe_merge1,dataframe_merge2,on='value' )
value
data1
data2
0
b
0
1
1
b
1
1
2
b
6
1
3
a
2
0
4
a
4
0
5
a
5
0
1 pd.merge(dataframe_merge1,dataframe_merge2,left_on='data1' ,right_on='data2' )
value_x
data1
value_y
data2
0
b
0
a
0
1
b
1
b
1
2
a
2
d
2
1 2 dataframe_merge3=pd.DataFrame({'key1' : ['foo' , 'foo' , 'bar' ], 'key2' : ['one' , 'two' , 'one' ], 'lval' : [1 , 2 , 3 ]}) dataframe_merge4=pd.DataFrame({'key1' : ['foo' , 'foo' , 'bar' , 'bar' ],'key2' : ['one' , 'one' , 'one' , 'two' ], 'rval' : [4 , 5 , 6 , 7 ]})
1 pd.merge(dataframe_merge3,dataframe_merge4,on=['key1' ,'key2' ],how='outer' )
key1
key2
lval
rval
0
foo
one
1.0
4.0
1
foo
one
1.0
5.0
2
foo
two
2.0
NaN
3
bar
one
3.0
6.0
4
bar
two
NaN
7.0
1 2 dataframe_merge5=pd.DataFrame({'key1' : ['Ohio' , 'Ohio' , 'Ohio' , 'Nevada' , 'Nevada' ], 'key2' : [2000 , 2001 , 2002 , 2001 , 2002 ],'data' : np.arange(5. )}) dataframe_merge6=pd.DataFrame(np.arange(12 ).reshape((6 , 2 )), index=[['Nevada' , 'Nevada' , 'Ohio' , 'Ohio' , 'Ohio' , 'Ohio' ], [2001 , 2000 , 2000 , 2000 , 2001 , 2002 ]],columns=['event1' , 'event2' ])
1 pd.merge(dataframe_merge5,dataframe_merge6,left_on=['key1' ,'key2' ],right_index=True ,how='outer' )
key1
key2
data
event1
event2
0
Ohio
2000
0.0
4.0
5.0
0
Ohio
2000
0.0
6.0
7.0
1
Ohio
2001
1.0
8.0
9.0
2
Ohio
2002
2.0
10.0
11.0
3
Nevada
2001
3.0
0.0
1.0
4
Nevada
2002
4.0
NaN
NaN
4
Nevada
2000
NaN
2.0
3.0
与merge()
函数功能类似的还有join()
函数,用法为:DataFrame1.join(DataFrame2)
。join()
函数支持传入一个list,代表同时对三个及以上的DataFrame进行合并。join()
函数可以使用的参数与merge()
函数类似。
由于这两个函数的作用相同,此处不再赘述。
拼接
Pandas中的concat
函数类似于NumPy中的concatenate
函数,传入一个由series或dataframe组成的list,将它们拼接在一起。
concat
函数支持的参数包括:
objs:一个包含了Pandas数据类型的list或者dict(必须传入的参数)
axis:进行拼接的方向,默认为行方向(即0)
join:'inner'或者'outer'其中的一个,默认为'outer'。inner代表只留下index或者columns中的交集部分进行拼接,而outer则代表拼接操作按照并集的方式进行,没有对应元素的使用NaN填充
keys:指明一系列拼接时使用的关键字,它们用于在拼接之后形成多层index,从而区分出数据的来源
levels:如果传入keys参数,levels参数用于指明被用作层级index的哪一层
names:如果使用key或者level参数,设定它们在index中对应的名字
verify_integrity:检查数据是否有重复并报错,默认为False,即允许数据重复
ignore_index:在合并的维度上丢掉原来所有的index,将其重新编号为0至n-1
下面是一些使用示例:
1 2 3 4 5 series_concat1=pd.Series([0 ,1 ],index=['a' ,'b' ]) series_concat2=pd.Series([2 ,3 ,4 ],index=['c' ,'d' ,'e' ]) series_concat3=pd.Series([5 ,6 ],index=['f' ,'g' ]) dataframe_concat1=pd.DataFrame(np.arange(6 ).reshape(3 , 2 ), index=['a' , 'b' , 'c' ],columns=['one' , 'two' ]) dataframe_concat2=pd.DataFrame(5 + np.arange(4 ).reshape(2 , 2 ), index=['a' , 'c' ], columns=['three' , 'four' ])
1 pd.concat([series_concat1,series_concat2,series_concat3])
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
1 pd.concat([series_concat1,series_concat2,series_concat3],axis=1 )
0
1
2
a
0.0
NaN
NaN
b
1.0
NaN
NaN
c
NaN
2.0
NaN
d
NaN
3.0
NaN
e
NaN
4.0
NaN
f
NaN
NaN
5.0
g
NaN
NaN
6.0
1 pd.concat([series_concat1,series_concat2,series_concat3],keys=['one' ,'two' ,'three' ],names=['upper' ,'lower' ])
upper lower
one a 0
b 1
two c 2
d 3
e 4
three f 5
g 6
dtype: int64
1 pd.concat([dataframe_concat1,dataframe_concat2],axis=1 ,ignore_index=True )
0
1
2
3
a
0
1
5.0
6.0
b
2
3
NaN
NaN
c
4
5
7.0
8.0
填充式合并
Pandas中含有一个x.combine_first(y)
函数,可以将y中有而x中没有的数据加入到x中,同时x中原有的数据不做任何修改:
1 2 dataframe_combine1=pd.DataFrame({'a' : [1. , np.nan, 5. , np.nan],'b' : [np.nan, 2. , np.nan, 6. ],'c' : range (2 , 18 , 4 )}) dataframe_combine2=pd.DataFrame({'a' : [5. , 4. , np.nan, 3. , 7. ],'b' : [np.nan, 3. , 4. , 6. , 8. ]})
1 dataframe_combine1.combine_first(dataframe_combine2)
a
b
c
0
1.0
NaN
2.0
1
4.0
2.0
6.0
2
5.0
4.0
10.0
3
3.0
6.0
14.0
4
7.0
8.0
NaN
1 dataframe_combine2.combine_first(dataframe_combine1)
a
b
c
0
5.0
NaN
2.0
1
4.0
3.0
6.0
2
5.0
4.0
10.0
3
3.0
6.0
14.0
4
7.0
8.0
NaN
重排与旋转
Pandas中的stack()
操作可以将某个columns“旋转”至index,与之对应的unstack()
操作则是将某个index“旋转”至columns。这两个操作都会把选择的那层index或者column插入到最内层。
使用示例:
1 2 dataframe_stack=pd.DataFrame(np.arange(6 ).reshape((2 , 3 )),index=pd.Index(['Ohio' , 'Colorado' ], name='state' ),columns=pd.MultiIndex.from_arrays([['a' ,'a' ,'b' ],['one' , 'two' , 'three' ]])) dataframe_stack
a
b
one
two
three
state
Ohio
0
1
2
Colorado
3
4
5
a
b
state
Ohio
one
0.0
NaN
three
NaN
2.0
two
1.0
NaN
Colorado
one
3.0
NaN
three
NaN
5.0
two
4.0
NaN
1 dataframe_stack.stack(level=0 )
one
three
two
state
Ohio
a
0.0
NaN
1.0
b
NaN
2.0
NaN
Colorado
a
3.0
NaN
4.0
b
NaN
5.0
NaN
1 dataframe_stack.unstack('state' )
state
a one Ohio 0
Colorado 3
two Ohio 1
Colorado 4
b three Ohio 2
Colorado 5
dtype: int32
pivot函数可以对一个DataFrame进行重排,要求这个DataFrame中的index为默认值。函数返回一个新的DataFrame。
如果传入三个及以上的列名称作为参数,第一个列中的内容会被转化为行的index,第二个列所包含的内容会被转化为column,之后,所有列中的内容会与index和column做对应,从而填充整个DataFrame;如果只传入两个列作为参数,那么第一列仍然作为index,原表格中的其它所有列都被保留下来,并与第二个列的内容共同构成一个多层的columns。例如:
1 dataframe_pivot=pd.DataFrame({'key' : ['foo' , 'bar' , 'baz' ], 'A' : [1 , 2 , 3 ], 'B' : [4 , 5 , 6 ], 'C' : [7 , 8 , 9 ]})
key
A
B
C
0
foo
1
4
7
1
bar
2
5
8
2
baz
3
6
9
1 dataframe_pivot.pivot('key' ,'B' )
A
C
B
4
5
6
4
5
6
key
bar
NaN
2.0
NaN
NaN
8.0
NaN
baz
NaN
NaN
3.0
NaN
NaN
9.0
foo
1.0
NaN
NaN
7.0
NaN
NaN
1 dataframe_pivot.pivot('key' ,'B' ,'A' )
B
4
5
6
key
bar
NaN
2.0
NaN
baz
NaN
NaN
3.0
foo
1.0
NaN
NaN
相对应地,pivot
的反操作为melt
。这一操作会将DataFrame变为两列或三列。
如果只传入value_vars参数,那么生成的DataFrame有两列,分别为variable和value,variable对应的是value_vars所包含的列名,value对应的是value_vars中的列名所指向的列里面的所有元素。
如果除了value_vars参数,还传入了id_vars参数,那么最终形成的DataFrame中会额外多出id_vars所对应的若干列。这些列中的内容为id_vars所对应列中的元素。
下面为一些示例:
1 dataframe_pivot.melt(id_vars=['key' ])
key
variable
value
0
foo
A
1
1
bar
A
2
2
baz
A
3
3
foo
B
4
4
bar
B
5
5
baz
B
6
6
foo
C
7
7
bar
C
8
8
baz
C
9
1 dataframe_pivot.melt(value_vars=['B' ,'C' ])
variable
value
0
B
4
1
B
5
2
B
6
3
C
7
4
C
8
5
C
9
1 dataframe_pivot.melt(id_vars=['A' ,'B' ],value_vars=['key' ,'C' ])
A
B
variable
value
0
1
4
key
foo
1
2
5
key
bar
2
3
6
key
baz
3
1
4
C
7
4
2
5
C
8
5
3
6
C
9
数据的分组
生成GroupBy变量
Series和DataFrame可以基于提供的一组关键字,按照行或列对其进行分组。
分组的方法有以下几类:
一个list或array,其中的元素作为分组的依据,要求大小与待分组轴向的大小相等
一个dict或Series,将待分组的数据以及这些数据所在的分组对应起来
一个列名,该列中的元素作为分组的依据,等同于传入一个Series
一个函数,可以作用于index或者是元素
一个index,适用于多层index的情况
使用groupby
函数,并传入上述三种参数中的其中一个,便可得到一个类型为SeriesGroupBy
或者DataFrameGroupBy
的变量。
下面为一些使用示例:
1 dataframe_groupby=pd.DataFrame({'key1' : ['a' , 'a' , 'b' , 'b' , 'a' ],'key2' : ['one' , 'two' , 'one' , 'two' , 'one' ], 'data1' : np.random.randn(5 ), 'data2' : np.random.randn(5 )})
key1
key2
data1
data2
0
a
one
0.773597
-0.769454
1
a
two
0.552522
-0.123829
2
b
one
-0.264872
-0.145577
3
b
two
-0.222394
-0.357799
4
a
one
-1.691627
0.530238
1 grouped_series=dataframe_groupby['data1' ].groupby(dataframe_groupby['key1' ])
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000001B04A2A2688>
1 grouped_series2=dataframe_groupby['data1' ].groupby([dataframe_groupby['key1' ],dataframe_groupby['key2' ]])
1 2 3 states = np.array(['Ohio' , 'California' , 'California' , 'Ohio' , 'Ohio' ]) years = np.array([2005 , 2005 , 2006 , 2005 , 2006 ]) grouped_arr=dataframe_groupby['data1' ].groupby([states,years])
1 grouped_colname=dataframe_groupby.groupby(['key1' ,'key2' ])
1 grouped_col=dataframe_groupby.groupby(dataframe_groupby.dtypes,axis=1 )
1 2 mapping={0 :'red' ,1 :'green' ,2 :'blue' ,3 :'red' ,4 :'blue' } grouped_mapping=dataframe_groupby.groupby(mapping)
1 2 func=lambda x: x>0 grouped_func=dataframe_groupby['data1' ].groupby(func)
1 2 3 columns = pd.MultiIndex.from_arrays([['US' , 'US' , 'US' , 'JP' , 'JP' ],[1 , 3 , 5 , 1 , 3 ]], names=['cty' , 'tenor' ]) dataframe_groupby2=pd.DataFrame(np.random.randn(4 , 5 ), columns=columns) grouped_hier=dataframe_groupby2.groupby(level='cty' , axis=1 )
GroupBy变量的使用
查看内容
groupby函数得到的
GroupBy`变量可以按照下面的两种方法查看或是使用每个分组的内容:
用于循环遍历,每个循环输出一个分组名称和内容
转换为list类型,list中的每个元素都是一个tuple,包含每个分组的名称和内容
索引
如果GroupBy
变量是从一个DataFrame分组而来的,可以使用DataFrame的列名对其进行索引,得到一个SeriesGroupBy
变量。
使用函数
GroupBy
变量也支持一些统计函数,包括:
count:统计分组中非NaN的数目
sum:统计所有非NaN元素的和
mean:计算所有非NaN元素的平均值
median:计算所有非NaN元素的中位数
std、var:统计非偏(即分母为n-1)标准差或方差
min、max:统计非NaN元素的最大与最小值
prod:统计所有非NaN元素的乘积
first、last:第一个或者最后一个非NaN元素
describe:对每个分组的数据进行统计,输出一些统计量
另外,还有几个比较特殊的函数用法:
agg:这一函数的用法有下面几种
可以自己定义函数,然后作为参数传入到agg
方法中,从而作用于每一个分组。传入的函数要求是聚合函数(即输出像统计函数一样会降维)
支持传入一个元素为统计函数名称的list
或是传入一个以二维tuple为元素的list,tuple的第一个元素为统计结果列的名称,第二个元素为统计函数的名称或是一个函数变量。
apply:传入一个函数作为输入参数,对每个分组调用这一函数,然后用concat方法将计算结果合起来,得到一个多重index的DataFrame。因此,每个分组的计算结果要满足concat操作的要求。
transform:对每个分组使用一个函数,要求函数的输出结果必须为一个标量,或是大小相同的array。这一操作完成之后,会生成一个与分组前规模相同的Series或者DataFrame,其中元素的值便是使用原始数据所在分组的函数输出来填充进去的。
下面为一些使用示例:
1 2 3 for name,group in grouped_func: print (name) print (group)
False
0 0.773597
Name: data1, dtype: float64
True
1 0.552522
2 -0.264872
3 -0.222394
4 -1.691627
Name: data1, dtype: float64
[(dtype('float64'),
data1 data2
0 0.773597 -0.769454
1 0.552522 -0.123829
2 -0.264872 -0.145577
3 -0.222394 -0.357799
4 -1.691627 0.530238),
(dtype('O'),
key1 key2
0 a one
1 a two
2 b one
3 b two
4 a one)]
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000001B04A2ACFC8>
data1
data2
key1
key2
a
one
-0.918030
-0.239216
two
0.552522
-0.123829
b
one
-0.264872
-0.145577
two
-0.222394
-0.357799
1 2 3 4 grouped_hier.describe()
count
mean
std
min
25%
50%
75%
max
cty
cty
tenor
JP
JP
1
4.0
-0.469233
1.009621
-1.229898
-0.940842
-0.832966
-0.361357
1.018895
3
4.0
0.167405
0.584559
-0.516235
-0.212018
0.221274
0.600696
0.743307
US
US
1
4.0
-0.356559
1.681193
-1.717014
-1.399371
-0.874332
0.168480
2.039443
3
4.0
-0.080853
0.551140
-0.674817
-0.479963
-0.060771
0.338339
0.472946
5
4.0
0.227364
1.239056
-1.354026
-0.461604
0.498428
1.187396
1.266626
1 2 3 def diff (arr ): return arr.max ()-arr.min () grouped_arr.agg(diff)
California 2005 0.00000
2006 0.00000
Ohio 2005 0.99599
2006 0.00000
Name: data1, dtype: float64
1 grouped_series.agg(['count' ,'max' ,'min' ])
count
max
min
key1
a
3
0.773597
-1.691627
b
2
-0.222394
-0.264872
1 grouped_mapping.agg([('sum_val' ,'sum' ),('bar' ,np.std)])
data1
data2
sum_val
bar
sum_val
bar
blue
-1.956499
1.008868
0.384661
0.477873
green
0.552522
NaN
-0.123829
NaN
red
0.551203
0.704271
-1.127252
0.291084
1 grouped_hier.transform(np.mean)
cty
US
JP
tenor
1
3
5
1
3
0
0.392919
0.392919
0.392919
0.786027
0.786027
1
-1.020843
-1.020843
-1.020843
-0.243295
-0.243295
2
-0.529225
-0.529225
-0.529225
-0.668838
-0.668838
3
0.877084
0.877084
0.877084
-0.477551
-0.477551
数据透视表
Pandas提供的pivot_table
函数可以用来构造数据透视表。这一函数支持的参数如下:
values:用于做数据透视表的数据列,默认使用全部的数据列
index:传入一个列名或者是其它用于分组的关键词,用作数据透视表的行
columns:传入一个列名或者是其它用于分组的关键词,用作数据透视表的列
aggfunc:传入一个聚合函数或者是聚合函数列表,默认为mean
fill_value:对数据透视表中NaN的数据的填充值
margins:是否加入每行/每列的总计以及总体的总计,默认为False
dropna:如果为True,则不包含全部为NaN的列
如果要做交叉表,即表中元素为数据频数的特殊数据透视表,可以用crosstab
函数。
下面为一些示例:
1 2 3 4 5 6 7 data=[[16.99 , 1.01 , 'No' , 'Sun' , 'Dinner' , 2 , 0.059447 ], [10.34 , 1.66 , 'No' , 'Sun' , 'Dinner' , 3 , 0.160542 ], [21.01 , 3.50 , 'No' , 'Sat' , 'Lunch' , 3 , 0.166587 ], [23.68 , 3.31 , 'Yes' , 'Sat' , 'Breakfast' , 2 , 0.139780 ], [24.59 , 3.61 , 'No' , 'Sun' , 'Dinner' , 4 , 0.146808 ], [25.29 , 4.71 , 'Yes' , 'Sat' , 'Lunch' , 4 , 0.186240 ]] dataframe_pivottable=pd.DataFrame(data,columns=['total_bill' ,'tip' ,'smoker' ,'day' ,'time' ,'size' ,'tip_pct' ])
1 dataframe_pivottable.pivot_table(index=['smoker' ,'day' ],columns='time' ,margins=True )
size
tip
tip_pct
total_bill
time
Breakfast
Dinner
Lunch
All
Breakfast
Dinner
Lunch
All
Breakfast
Dinner
Lunch
All
Breakfast
Dinner
Lunch
All
smoker
day
No
Sat
NaN
NaN
3.0
3
NaN
NaN
3.500
3.500000
NaN
NaN
0.166587
0.166587
NaN
NaN
21.01
21.010000
Sun
NaN
3.0
NaN
3
NaN
2.093333
NaN
2.093333
NaN
0.122266
NaN
0.122266
NaN
17.306667
NaN
17.306667
Yes
Sat
2.0
NaN
4.0
3
3.31
NaN
4.710
4.010000
0.13978
NaN
0.186240
0.163010
23.68
NaN
25.29
24.485000
All
2.0
3.0
3.5
3
3.31
2.093333
4.105
2.966667
0.13978
0.122266
0.176414
0.143234
23.68
17.306667
23.15
20.316667
1 pd.crosstab([dataframe_pivottable['smoker' ],dataframe_pivottable['time' ]],dataframe_pivottable['day' ],margins=True )
day
Sat
Sun
All
smoker
time
No
Dinner
0
3
3
Lunch
1
0
1
Yes
Breakfast
1
0
1
Lunch
1
0
1
All
3
3
6
参考
Python for Data Analysis, 2nd Edition