Pandas类似R语言中的数据框(DataFrame),Pandas基于Numpy,但是对于数据框结构的处理比Numpy要来的容易。
1. Pandas的基本数据结构和使用
Pandas有两个主要的数据结构:Series和DataFrame。Series类似Numpy中的一维数组,DataFrame则是使用较多的多维表格数据结构。
Series的创建
1
2
3
4
5
6
7
8
9
10
11
|
>>> import numpy as np
>>> import pandas as pd
>>>s = pd.Series([ 1 , 2 , 3 ,np.nan, 44 , 1 ]) # np.nan创建一个缺失数值
>>>s # 若未指定,Series会自动建立index,此处自动建立索引0-5
0 1.0
1 2.0
2 3.0
3 NaN
4 44.0
5 1.0
dtype: float64
|
DataFrame的创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>>dates = pd.date_range( '20170101' ,periods = 6 )
>>>dates
DatetimeIndex([ '2017-01-01' , '2017-01-02' , '2017-01-03' , '2017-01-04' ,
'2017-01-05' , '2017-01-06' ],
dtype = 'datetime64[ns]' , freq = 'D' )
>>>df = pd.DataFrame(np.random.randn( 6 , 4 ),index = dates,columns = [ 'a' , 'b' , 'c' , 'd' ])
>>>df
a b c d
2017 - 01 - 01 - 1.993447 1.272175 - 1.578337 - 1.972526
2017 - 01 - 02 0.092701 - 0.503654 - 0.540655 - 0.126386
2017 - 01 - 03 0.191769 - 0.578872 - 1.693449 0.457891
2017 - 01 - 04 2.121120 0.521884 - 0.419368 - 1.916585
2017 - 01 - 05 1.642063 0.222134 0.108531 - 1.858906
2017 - 01 - 06 0.636639 0.487491 0.617841 - 1.597920
|
DataFrame可以跟Numpy一样根据索引取出其中的数据,只是DataFrame索引方式更加多样化。DataFrame不仅可以根据默认的行列编号来索引,还可以根据标签序列来索引。
还可以采用字典的方式创建DataFrame:
1
2
3
4
5
|
>>>df2 = pd.DataFrame({ 'a' : 1 , 'b' : 'hello kitty' , 'c' :np.arange( 2 ), 'd' :[ 'o' , 'k' ]})
>>>df2
a b c d
0 1 hello kitty 0 o
1 1 hello kitty 1 k
|
对于DataFrame的一些属性也可以采用相应的方法查看
1
2
3
4
5
6
7
8
|
dtype # 查看数据类型
index # 查看行序列或者索引
columns # 查看各列的标签
values # 查看数据框内的数据,也即不含表头索引的数据
describe # 查看数据的一些信息,如每一列的极值,均值,中位数之类的,只能对数值型数据统计信息
transpose # 转置,也可用T来操作
sort_index # 排序,可按行或列index排序输出
sort_values # 按数据值来排序
|
一些例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
>>>df2.dtypes
a int64
b object
c int64
d object
dtype: object
>>>df2.index
RangeIndex(start = 0 , stop = 2 , step = 1 )
>>>df2.columns
Index([ 'a' , 'b' , 'c' , 'd' ], dtype = 'object' )
>>>df2.values
array([[ 1 , 'hello kitty' , 0 , 'o' ],
[ 1 , 'hello kitty' , 1 , 'k' ]], dtype = object )
>>>df2.describe # 只能对数值型数据统计信息
a c
count 2.0 2.000000
mean 1.0 0.500000
std 0.0 0.707107
min 1.0 0.000000
25 % 1.0 0.250000
50 % 1.0 0.500000
75 % 1.0 0.750000
max 1.0 1.000000
>>>df2.T
0 1
a 1 1
b hello kitty hello kitty
c 0 1
d o k
>>>df2.sort_index(axis = 1 ,ascending = False ) # axis=1 按列标签从大到小排列
d c b a
0 o 0 hello kitty 1
1 k 1 hello kitty 1
>>>df2.sort_index(axis = 0 ,ascending = False ) # 按行标签从大到小排序
a b c d
1 1 hello kitty 1 k
0 1 hello kitty 0 o
>>>df2.sort_values(by = "c" ,ascending = False ) # 按c列的值从大到小排序
a b c d
1 1 hello kitty 1 k
0 1 hello kitty 0 o
|
2. 从DataFrame中筛选取出目的数据
从DataFrame中取出目的数据方法有多种,一般常用的有:
- - 直接根据索引选取
- - 根据标签选取(纵向选择列):loc
- - 根据序列(横向选择行): iloc
- - 组合使用标签序列来选取特定位置的数据: ix
- - 通过逻辑判断筛选
简单选取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
>>> import numpy as np
>>> import pandas as pd
>>>dates = pd.date_range( '20170101' ,periods = 6 )
>>>df = pd.DataFrame(np.arange( 24 ).reshape(( 6 , 4 )),index = dates,columns = [ 'a' , 'b' , 'c' , 'd' ])
>>>df
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 10 11
2017 - 01 - 04 12 13 14 15
2017 - 01 - 05 16 17 18 19
2017 - 01 - 06 20 21 22 23
>>>df[ 'a' ] # 根据表签直接选取a列,也可用df.a,结果相同
2017 - 01 - 01 0
2017 - 01 - 02 4
2017 - 01 - 03 8
2017 - 01 - 04 12
2017 - 01 - 05 16
2017 - 01 - 06 20
Freq: D, Name: a, dtype: int64
>>>df[ 0 : 3 ] # 选择前3行,也可用行标签 df['2017-01-01':'2017-01-03'],结果相同,但是无法用此法选择多列
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 10 11
|
loc使用显式的行标签来选取数据
DataFrame行的表示方式有两种,一种是通过显式的行标签来索引,另一种是通过默认隐式的行号来索引。loc方法是通过行标签来索引选取目标行,可以配合列标签来选取特定位置的数据。
1
2
3
4
5
6
7
8
9
|
>>>df.loc[ '2017-01-01' : '2017-01-03' ]
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 10 11
>>>df.loc[ '2017-01-01' ,[ 'a' , 'b' ]] # 选取特定行的a,b列
a 0
b 1
Name: 2017 - 01 - 01 00 : 00 : 00 , dtype: int64
|
iloc使用隐式的行序列号来选取数据
使用iloc可以搭配列序列号来更简单的选取特定位点的数据
1
2
3
4
5
6
|
>>>df.iloc[ 3 , 1 ]
13
>>>df.iloc[ 1 : 3 , 2 : 4 ]
c d
2017 - 01 - 02 6 7
2017 - 01 - 03 10 11
|
ix利用ix可以混用显式标签与隐式序列号
loc只能使用显式标签来选取数据,而iloc只能使用隐式序列号来选取数据,ix则能将二者结合起来使用。
1
2
3
4
|
>>> df.ix[ 3 : 5 ,[ 'a' , 'b' ]]
a b
2017 - 01 - 04 12 13
2017 - 01 - 05 16 17
|
使用逻辑判断来选取数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>>df
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 10 11
2017 - 01 - 04 12 13 14 15
2017 - 01 - 05 16 17 18 19
2017 - 01 - 06 20 21 22 23
>>>df[df[ 'a' ]> 5 ] # 等价于df[df.a>5]
a b c d
2017 - 01 - 03 8 9 10 11
2017 - 01 - 04 12 13 14 15
2017 - 01 - 05 16 17 18 19
2017 - 01 - 06 20 21 22 23
|
3. Pandas设置特定位置值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
>>> import numpy as np
>>> import pandas as pd
>>>dates = pd.date_range( '20170101' ,periods = 6 )
>>>datas = np.arange( 24 ).reshape(( 6 , 4 ))
>>>columns = [ 'a' , 'b' , 'c' , 'd' ]
>>>df = pd.DataFra me(data = datas,index = dates,colums = columns)
>>>df.iloc[ 2 , 2 : 4 ] = 111 # 将第2行2,3列位置的数据改为111
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 111 111
2017 - 01 - 04 12 13 14 15
2017 - 01 - 05 16 17 18 19
2017 - 01 - 06 20 21 22 23
>>>df.b[df[ 'a' ]> 10 ] = 0 # 等价于df.b[df.a>10] # 以a列大于10的数的位置为参考,改变b列相应行的数值为0
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 111 111
2017 - 01 - 04 12 0 14 15
2017 - 01 - 05 16 0 18 19
2017 - 01 - 06 20 0 22 23
>>>df[ 'f' ] = np.nan # 新建f列并设置数值为np.nan
a b c d f
2017 - 01 - 01 0 1 2 3 NaN
2017 - 01 - 02 4 5 6 7 NaN
2017 - 01 - 03 8 9 111 111 NaN
2017 - 01 - 04 12 0 14 15 NaN
2017 - 01 - 05 16 0 18 19 NaN
2017 - 01 - 06 20 0 22 23 NaN
>>>
# 用上面的方法也可以加上`Series`序列,但是必须与列长度一致
>>>df[ 'e' ] = pd.Series(np.arange( 6 ),index = dates)
>>>df
a b c d f e
2017 - 01 - 01 0 1 2 3 NaN 0
2017 - 01 - 02 4 5 6 7 NaN 1
2017 - 01 - 03 8 9 111 111 NaN 2
2017 - 01 - 04 12 0 14 15 NaN 3
2017 - 01 - 05 16 0 18 19 NaN 4
2017 - 01 - 06 20 0 22 23 NaN 5
|
4. 处理丢失数据
有时候我们的数据中会有一些空的或者缺失(NaN)数据,使用dropna可以选择性的删除或填补这些NaN数据。drop函数可以选择性的删除行或者列,drop_duplicates去除冗余。fillna则将NaN值用其他值替换。操作后不改变原值,若要保存更改需重新赋值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
>>> import numpy as np
>>> import pandas as pd
>>>df = pd.DataFrame(np.arange( 24 ).reshape( 6 , 4 ),index = pd.date_range( '20170101' ,periods = 6 ),columns = [ 'a' , 'b' , 'c' , 'd' ])
>>>df
a b c d
2017 - 01 - 01 0 1 2 3
2017 - 01 - 02 4 5 6 7
2017 - 01 - 03 8 9 10 11
2017 - 01 - 04 12 13 14 15
2017 - 01 - 05 16 17 18 19
2017 - 01 - 06 20 21 22 23
>>>df.iloc[ 1 , 3 ] = np.nan
>>>di.iloc[ 3 , 2 ] = np.nan
>>>df.
a b c d
2017 - 01 - 01 0 1 2.0 3.0
2017 - 01 - 02 4 5 6.0 NaN
2017 - 01 - 03 8 9 10.0 11.0
2017 - 01 - 04 12 13 NaN 15.0
2017 - 01 - 05 16 17 18.0 19.0
2017 - 01 - 06 20 21 22.0 23.0
>>>df.dropna(axis = 0 ,how = 'any' ) # axis=0(1)表示将含有NaN的行(列)删除。
# how='any'表示只要行(或列,视axis取值而定)含有NaN则将该行(列)删除,
# how='all'表示当某行(列)全部为NaN时才删除
a b c d
2017 - 01 - 01 0 1 2.0 3.0
2017 - 01 - 03 8 9 10.0 11.0
2017 - 01 - 05 16 17 18.0 19.0
2017 - 01 - 06 20 21 22.0 23.0
>>>df.fillna(value = 55 )
a b c d
2017 - 01 - 01 0 1 2.0 3.0
2017 - 01 - 02 4 5 6.0 55.0
2017 - 01 - 03 8 9 10.0 11.0
2017 - 01 - 04 12 13 55.0 15.0
2017 - 01 - 05 16 17 18.0 19.0
2017 - 01 - 06 20 21 22.0 23.0
|
还可以利用函数来检查数据中是否有或者全部为NaN
1
2
3
4
|
>>>np. any (df.isnull()) = = True
True
>>>np. all (df.isnull()) = = True
False
|
5. 数据的导入以及导出
一般excel文件以csv方式读入,pd.read_csv(file),data保存为filedata.to_csv(file)。
6. 数据添加合并
本节主要学习Pandas的一些简单基本的数据添加合并方法:concat,append。
concat合并方式类似于Numpy的concatenate方法,可横向或者竖向合并。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
>>> import numpy as np
>>> import pandas as pd
>>> df1 = pd.DataFrame(np.ones(( 3 , 4 )) * 0 ,columns = [ 'a' , 'b' , 'c' , 'd' ])
>>> df2 = pd.DataFrame(np.ones(( 3 , 4 )) * 1 ,columns = [ 'a' , 'b' , 'c' , 'd' ])
>>> df3 = pd.DataFrame(np.ones(( 3 , 4 )) * 2 ,columns = [ 'a' , 'b' , 'c' , 'd' ])
>>>res = pd.concat([df1,df2,df3],axis = 0 )
# axis=0表示按行堆叠合并,axis=1表示按列左右合并
>>>res
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
0 1.0 1.0 1.0 1.0
1 1.0 1.0 1.0 1.0
2 1.0 1.0 1.0 1.0
0 2.0 2.0 2.0 2.0
1 2.0 2.0 2.0 2.0
2 2.0 2.0 2.0 2.0
>>>
# 使用ignore_index=True参数可以重置行标签
>>>res = pd.concat([df1,df2,df3],axis = 0 ,ignore_index = True )
>>>res
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0
6 2.0 2.0 2.0 2.0
7 2.0 2.0 2.0 2.0
8 2.0 2.0 2.0 2.0
|
join参数提供了更多样化的合并方式。join=outer为默认值,表示将几个合并的数据都用上,具有相同列标签的合二为一,上下合并,不同列标签的独自成列,原来没有数值的位置以NaN填充;join=inner则只将具有相同列标签的(行)列上下合并,其余的列舍弃。简言之,outer代表并集,inner代表交集**。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
>>> import numpy as np
>>> import pandas as pd
>>>df1 = pd.DataFrame(np.ones(( 3 , 4 )),index = [ 1 , 2 , 3 ],columns = [ 'a' , 'b' , 'c' , 'd' ])
>>>df2 = pd.DataFrame(np.ones(( 3 , 4 )) * 2 ,index = [ 1 , 2 , 3 ],columns = [ 'b' , 'c' , 'd' , 'e' ])
>>>res = pd.concat([df1,df2],axis = 0 ,join = 'outer' )
>>>res
a b c d e
1 1.0 1.0 1.0 1.0 NaN
2 1.0 1.0 1.0 1.0 NaN
3 1.0 1.0 1.0 1.0 NaN
1 NaN 2.0 2.0 2.0 2.0
2 NaN 2.0 2.0 2.0 2.0
3 NaN 2.0 2.0 2.0 2.0
>>>res1 = pd.concat([df1,df2],axis = 1 ,join = 'outer' )
# axis=1表示按列左右合并具有相同的行标签的,其余的各成一行,NaN补齐空缺
>>>res1
a b c d b c d e
1 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
2 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
3 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
>>>res2 = pd.concat([df1,df2],axis = 0 ,join = 'inner' ,ignore_index = True )
# 将具有相同列标签的列上下合并
>>>res2
b c d
0 1.0 1.0 1.0
1 1.0 1.0 1.0
2 1.0 1.0 1.0
3 2.0 2.0 2.0
4 2.0 2.0 2.0
5 2.0 2.0 2.0
|
join_axes参数可以设定参考系,以设定的参考来合并,参考系中没有的舍弃掉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
>>> import numpy as np
>>> import pandas as pd
>>>df1 = pd.DataFrame(np.ones(( 3 , 4 )),index = [ 1 , 2 , 3 ],columns = [ 'a' , 'b' , 'c' , 'd' ])
>>> df2 = pd.DataFrame(np.ones(( 3 , 4 )) * 2 ,index = [ 2 , 3 , 4 ],columns = [ 'b' , 'c' , 'd' , 'e' ])
>>>res3 = pd.concat([df1,df2],axis = 0 ,join_axes = [df1.columns])
# 以df1的列标签为参考上下合并拥有相同列标签的列
>>>res3
a b c d
1 1.0 1.0 1.0 1.0
2 1.0 1.0 1.0 1.0
3 1.0 1.0 1.0 1.0
2 NaN 2.0 2.0 2.0
3 NaN 2.0 2.0 2.0
4 NaN 2.0 2.0 2.0
>>>res4 = pd.concat([df1,df2],axis = 1 ,join_axes = [df1.index])
# 以df1行标签为参考,左右合并拥有相同行标签的各列
a b c d b c d e
1 1.0 1.0 1.0 1.0 NaN NaN NaN NaN
2 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
3 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
|
append只有上下合并,没有左右合并
1
2
3
4
5
6
7
8
9
10
11
|
>>>df1 = pd.DataFrame(np.ones(( 3 , 4 )),index = [ 1 , 2 , 3 ],columns = [ 'a' , 'b' , 'c' , 'd' ])
>>> df2 = pd.DataFrame(np.ones(( 3 , 4 )) * 2 ,index = [ 2 , 3 , 4 ],columns = [ 'b' , 'c' , 'd' , 'e' ])
>>>res5 = df1.append(df2,ignore_index = True )
>>>res5
a b c d e
0 1.0 1.0 1.0 1.0 NaN
1 1.0 1.0 1.0 1.0 NaN
2 1.0 1.0 1.0 1.0 NaN
3 NaN 2.0 2.0 2.0 2.0
4 NaN 2.0 2.0 2.0 2.0
5 NaN 2.0 2.0 2.0 2.0
|
7. Pandas高级合并:merge
merge合并与concat类似,只是merge可以通过一个或多个键将两个数据集的行连接起来。
1
2
|
merge(left, right, how = 'inner' , on = None , left_on = None , right_on = None , left_index = False , right_index = False ,
sort = False , suffixes = ( '_x' , '_y' ), copy = True , indicator = False )
|
参数说明:
- left与right:两个不同的DataFrame
- how:指的是合并(连接)的方式有inner(内连接),left(左外连接),right(右外连接),outer(全外连接);默认为inner
- on : 指的是用于连接的列索引名称。必须存在右右两个DataFrame对象中,如果没有指定且其他参数也未指定则以两个DataFrame的列名交集做为连接键
- left_on:左侧DataFrame中用作连接键的列名;这个参数中左右列名不相同,但代表的含义相同时非常有用。
- right_on:右侧DataFrame中用作 连接键的列名
- left_index:使用左侧DataFrame中的行索引做为连接键
- right_index:使用右侧DataFrame中的行索引做为连接键
- sort:默认为True,将合并的数据进行排序。在大多数情况下设置为False可以提高性能
- suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为('_x','_y')
- copy:默认为True,总是将数据复制到数据结构中;大多数情况下设置为False可以提高性能
- indicator:显示合并数据中来源情况;如只来自己于左边(left_only)、两者(both)
1
2
3
4
5
6
7
8
9
10
|
>>> import pandas as pd
>>>df1 = pd.DataFrame({ 'key' :[ 'k0' , 'k1' , 'k2' , 'k3' ], 'A' :[ 'a0' , 'a1' , 'a2' , 'a3' ], 'B' :[ 'b0' , 'b1' , 'b2' , 'b3' ]})
>>>df2 = pd.DataFrame({ 'key' :[ 'k0' , 'k1' , 'k2' , 'k3' ], 'C' :[ 'c0' , 'c1' , 'c2' , 'c3' ], 'D' :[ 'd0' , 'd1' , 'd2' , 'd3' ]})
>>> res = pd.merge(df1,df2,on = 'key' ,indicator = True )
>>>res
A B key C D _merge
0 a0 b0 k0 c0 d0 both
1 a1 b1 k1 c1 d1 both
2 a2 b2 k2 c2 d2 both
3 a3 b3 k3 c3 d3 both
|
依据行index合并与依据列key合并用法类似
1
2
3
4
5
6
7
|
>>>res2 = pd.merge(df1,df2,left_index = True ,right_index = True ,indicator = True )
>>>res2
A B key_x C D key_y _merge
0 a0 b0 k0 c0 d0 k0 both
1 a1 b1 k1 c1 d1 k1 both
2 a2 b2 k2 c2 d2 k2 both
3 a3 b3 k3 c3 d3 k3 both
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.jianshu.com/p/b3ba9403945c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation