文章目录
1.pandas数据结构介绍
1.1 Series
Series是一种一维的数据型对象,它包含一个值序列(与Numpy中的类型相似),并且包含数据的标签,称为索引(index)
In [2]: obj = pd.Series([1,2,3])
In [3]: obj
Out[3]:
0 1
1 2
2 3
dtype: int64
In [4]: obj.values
Out[4]: array([1, 2, 3], dtype=int64)
In [5]: obj.index
Out[5]: RangeIndex(start=0, stop=3, step=1)
pd.Series(序列)可以生成一个Series的对象,序列是有序的数据结构,集合不行,但是字典可以,列表,元组等都行
Series的属性
-
index
-
values
-
name
-
index.name
In [32]: obj.name = 'zhangfan' In [33]: obj.index.name = 'zf' In [34]: obj Out[34]: zf a 1 b 2 c 3 Name: zhangfan, dtype: int64
Series与Numpy数组几乎相同,唯一不同点是,Series既可以像Numpy数组一样,通过整数来索引值,也可以通过Series自定义的其他索引来索引值
-
可以对Series使用Numpy函数或Numpy风格的操作
In [17]: obj Out[17]: a 1 b 2 c 3 dtype: int64 In [18]: obj[obj>1]#bool数组 Out[18]: b 2 c 3 dtype: int64 In [19]: np.exp(obj)#通用函数 Out[19]: a 2.718282 b 7.389056 c 20.085537 dtype: float64 In [20]: obj + obj#类似numpy数组中的逐元素操作 Out[20]: a 2 b 4 c 6 dtype: int64 In [21]: obj[0]#通过整数索引来索引值 Out[21]: 1
-
当pd.Series(字典,index)传入的是一个字典的时候,index参数表示的是,选择那些键所对应的键值对构成Series,不存在的键的值对应NaN
In [27]: pd.Series(dict(zip([1,2,3],list('abc'))),index=[3,2,1]) Out[27]: 3 c 2 b 1 a dtype: object
-
pd.isnull(Series)或者Series.isnull()可以用来判断Series中的值是否是NaN
pd.notnull(Series)或者Series.notnull()是上面的对立操作
-
自动对齐
当把两个Series相加的时候,两个Series会自动对齐index,将index相同的值相加在一起
1.2 DataFrame
简介:DataFrame表示的是矩阵的数据表,包含以排序的列集合,每一列可以是不同的值类型。DataFrame中既有行索引也有列索引,它可以被视作一个共享相同索引的Series的字典
1.2.1 属性:
- index
- columns
- index.name
- columns.name
- values
- dtypes
In [60]: df1
Out[60]:
zf a b c
zhangfan
0 1 4 7
1 2 5 8
2 3 6 9
In [61]: df1.index
Out[61]: RangeIndex(start=0, stop=3, step=1, name='zhangfan')
In [62]: df1.columns
Out[62]: Index(['a', 'b', 'c'], dtype='object', name='zf')
In [63]: df1.index.name
Out[63]: 'zhangfan'
In [64]: df1.columns.name
Out[64]: 'zf'
In [82]: df1.values
Out[82]:
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]], dtype=int64)
In [85]: df1.dtypes
Out[85]:
zf
a int64
b int64
c int64
dtype: object
1.2.2 生成DataFrame
-
包含等长度列表或Numpy数组的字典来形成DataFrame
In [35]: data = {'a':[1,2,3],'b':[4,5,6],'c':[7,8,9]} In [36]: df1 = pd.DataFrame(data) In [37]: df1 Out[37]: a b c 0 1 4 7 1 2 5 8 2 3 6 9
-
因为传入的是一个字典,因此可以通过columns属性来改变列的顺序或选择出现的列
In [39]: df2 = pd.DataFrame(data,columns=['b','c','e']) In [40]: df2 Out[40]: b c e 0 4 7 NaN 1 5 8 NaN 2 6 9 NaN
-
df.head(nums)
df.head()表示选择df的前几行,nums参数表示前几行,如果不给nums参数,则默认表示前五行
In [41]: df1.head(2) Out[41]: a b c 0 1 4 7 1 2 5 8
-
DataFrame中的一列,可以按字典型标记或属性那样检索为Series
DataFrame中选取的列是数据的视图,而不是拷贝,因此对选取的列进行修改会映射到原DataFrame
In [47]: df1 Out[47]: a b c 0 1 4 7 1 2 5 8 2 3 6 9 In [48]: df1['a']#字符串列名需要加引号 Out[48]: 0 1 1 2 2 3 Name: a, dtype: int64 In [49]: df1.a#字符串列名不需要加引号 Out[49]: 0 1 1 2 2 3 Name: a, dtype: int64
-
DataFrame中的一行,可以通过df.loc[行名]来索引
-
增加一列和删除一列
In [65]: df1['d'] = np.arange(3) In [66]: df1 Out[66]: zf a b c d zhangfan 0 1 4 7 0 1 2 5 8 1 2 3 6 9 2 In [67]: del df1['d'] In [68]: df1 Out[68]: zf a b c zhangfan 0 1 4 7 1 2 5 8 2 3 6 9
-
增加一行和删除一行
In [68]: df1 Out[68]: zf a b c zhangfan 0 1 4 7 1 2 5 8 2 3 6 9 In [112]: df1.drop(2) Out[112]: zf a b c zhangfan 0 1 4 7 1 2 5 8
-
-
包含字典的嵌套字典
In [69]: pop = {'a':{'m':1,'n':2,'o':3},'b':{'m':4,'n':5,'o':6},'c':{'m':7,'n':8,'o':9}} In [70]: df3 = pd.DataFrame(pop) In [71]: df3 Out[71]: a b c m 1 4 7 n 2 5 8 o 3 6 9
-
DataFrame可以像Numpy中的数组一样转置
In [71]: df3 Out[71]: a b c m 1 4 7 n 2 5 8 o 3 6 9 In [72]: df3.T Out[72]: m n o a 1 2 3 b 4 5 6 c 7 8 9
-
可以显示的给定index参数,让DataFrame按照给定的index序列排列
In [73]: pop Out[73]: {'a': {'m': 1, 'n': 2, 'o': 3}, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': {'m': 7, 'n': 8, 'o': 9}} In [74]: df3 = pd.DataFrame(pop,index=['o','n','m' ...: ]) In [75]: df3 Out[75]: a b c o 3 6 9 n 2 5 8 m 1 4 7
-
-
包含Series的字典也可以用于构造DataFrame
In [75]: df3 Out[75]: a b c o 3 6 9 n 2 5 8 m 1 4 7 In [77]: pd.DataFrame({'e':df3.a,'f':df3.c}) Out[77]: e f o 3 9 n 2 8 m 1 7
1.3 索引对象(pd.Index())
索引对象是不可变对象,索引对象的这个特点使得在多种数据结构中分享索引对象更为安全
In [86]: index = pd.Index([1,2,3])
In [87]: index
Out[87]: Int64Index([1, 2, 3], dtype='int64')
In [88]: index[0] = 0
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-88-1441e135a2b4> in <module>()
----> 1 index[0] = 0
~\AppData\Roaming\Python\Python37\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
4079
4080 def __setitem__(self, key, value):
-> 4081 raise TypeError("Index does not support mutable operations")
4082
4083 def __getitem__(self, key):
TypeError: Index does not support mutable operations(翻译:索引不支持可变操作)
与Python集合不同:pandas索引对象可以包含重复的标签
In [91]: dup_labels = pd.Index(['a','a','b','b'])
In [92]: dup_labels
Out[92]: Index(['a', 'a', 'b', 'b'], dtype='object')
根据重复标签进行筛选,会选取所有重复标签对应的数据
1.3.1 索引对象常用方法
- index1.append(index2) 将索引对象index2添加到index1后面,产生一个新的索引
- index.unique() 计算索引的唯一值序列
- 索引对象常用方法
1.4 重建索引
重建索引,不会改变索引,只会重新排列索引,
-
series.reindex() , 会将数据按照新的索引进行排列
series.reindex()有个参数method,可以传入‘ffill’表示前向填充,'bfill’表示后向填充
-
在DataFrame中,reindex可以改变行索引和列索引,也可以同时改变二者。当仅传入一个序列时,结果中的行会重建索引
In [108]: df3 Out[108]: a b c o 3 6 9 n 2 5 8 m 1 4 7 In [106]: df3.reindex(columns=['a','x']) Out[106]: a x o 3 NaN n 2 NaN m 1 NaN In [109]: df3.reindex(columns=['a','x'],method='ffill')#对于不存在的columns,ffill会填充最后一列 Out[109]: a x o 3 9 n 2 8 m 1 7 In [110]: df3.reindex(['o','x'],method='bfill')#对于不存在的行,bfill会填充第一行 Out[110]: a b c o 3 6 9 x 3 6 9
1.5 删除df的行列
df.drop(行名或列名,axis=0)
行名或列名可以是一个列表
In [115]: df1
Out[115]:
zf a b c
zhangfan
0 1 4 7
1 2 5 8
2 3 6 9
In [116]: df1.drop(2)
Out[116]:
zf a b c
zhangfan
0 1 4 7
1 2 5 8
In [117]: df1.drop(['b','c'],axis=1)#axis = 1可以用axis='columns'来代替
Out[117]:
zf a
zhangfan
0 1
1 2
2 3
1.6索引、选择与过滤
Series的索引支持nupy中的索引方式,另外Series还有独有的索引方式
In [126]: obj
Out[126]:
zf
a 1
b 2
c 3
Name: zhangfan, dtype: int64
In [127]: obj['a':'c']#与普通的切片不同的是,Series的切片会包含尾部的
Out[127]:
zf
a 1
b 2
c 3
Name: zhangfan, dtype: int64
1.6.1 DataFrame的索引
-
行索引
In [130]: df3 Out[130]: a b c o 3 6 9 n 2 5 8 m 1 4 7 In [131]: df3['a'] Out[131]: o 3 n 2 m 1 Name: a, dtype: int64 In [132]: df3[['a','c']]#列名必须用中括号括起来 Out[132]: a c o 3 9 n 2 8 m 1 7 In [133]: df3.a Out[133]: o 3 n 2 m 1 Name: a, dtype: int64
-
列索引
In [137]: df3 Out[137]: a b c o 3 6 9 n 2 5 8 m 1 4 7 In [138]: df3[df3['a']>1]#bool索引 Out[138]: a b c o 3 6 9 n 2 5 8 In [139]: df3[:2]#整数行索引必须这样,不能通过单个整数直接索引 Out[139]: a b c o 3 6 9 n 2 5 8 In [140]: df3[0] ######行索引不能这样索引,这样会报错
-
省去麻烦,直接使用loc和iloc选择器,也支持Series
1.7 算术和数据对齐
将两个DataFrame相加时,pandas会自动将两者按照index和columns全相同的元素相加,不相同的则只保留行和列的索引,值为NaN
In [140]: df5 = pd.DataFrame(np.arange(9).reshape((3,3)),columns=list('bcd'),index=['Ohio','Texas','Colorado'])
In [141]: df6 = pd.DataFrame(np.arange(12).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
In [142]: df5
Out[142]:
b c d
Ohio 0 1 2
Texas 3 4 5
Colorado 6 7 8
In [143]: df6
Out[143]:
b d e
Utah 0 1 2
Ohio 3 4 5
Texas 6 7 8
Oregon 9 10 11
In [144]: df5 + df6
Out[144]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
1.7.1 使用填充值的算术方法
- add, radd +
- sub, rsub -
- div, rdiv /
- floordiv, rfloordiv //
- mul, rmul *
- pow, rpow **
In [142]: df5
Out[142]:
b c d
Ohio 0 1 2
Texas 3 4 5
Colorado 6 7 8
In [143]: df6
Out[143]:
b d e
Utah 0 1 2
Ohio 3 4 5
Texas 6 7 8
Oregon 9 10 11
In [144]: df5 + df6
Out[144]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
In [145]: 3//2
Out[145]: 1
In [146]: df5.add(df6,fill_value=0)
Out[146]:
b c d e
Colorado 6.0 7.0 8.0 NaN
Ohio 3.0 1.0 6.0 5.0
Oregon 9.0 NaN 10.0 11.0
Texas 9.0 4.0 12.0 8.0
Utah 0.0 NaN 1.0 2.0
1.8 函数应用和映射
Numpy中的通用函数(逐元素数组方法)对DataFrame对象也有效
In [151]: df4 = pd.DataFrame(np.random.randn(4,3))
In [152]: df4
Out[152]:
0 1 2
0 -1.971583 1.182724 -1.030719
1 -0.450175 0.656434 -0.594173
2 -0.310988 0.398418 -0.659847
3 -0.054048 0.114076 -1.713716
In [153]: np.abs(df4)
Out[153]:
0 1 2
0 1.971583 1.182724 1.030719
1 0.450175 0.656434 0.594173
2 0.310988 0.398418 0.659847
3 0.054048 0.114076 1.713716
1.8.1 apply函数
df.apply(函数名,axis)可以将“函数”应用到df的每一个axis上面
In [154]: df4
Out[154]:
0 1 2
0 -1.971583 1.182724 -1.030719
1 -0.450175 0.656434 -0.594173
2 -0.310988 0.398418 -0.659847
3 -0.054048 0.114076 -1.713716
In [155]: df4.apply(lambda x:x.max()-x.min(),axis='columns')
Out[155]:
0 3.154307
1 1.250607
2 1.058265
3 1.827792
dtype: float64
大部分常用的数组统计(比如sum和mean)都是DataFrame的方法,因此计算统计值时使用apply并不是必需的
传递给apply的函数并不是一定要返回一个标量值,也可以返回带有多个值的Series:
In [157]: def f(x):
...: return pd.Series([x.max(),x.min()],index=['max','min'])
...:
...:
In [158]: df4.apply(f)
Out[158]:
0 1 2
max -0.054048 1.182724 -0.594173
min -1.971583 0.114076 -1.713716
1.8.2 applymap函数
df.applymap(函数名)可以将函数应用到df中的每一个元素
In [159]: df4.applymap(lambda x:'%.2f' % x)
Out[159]:
0 1 2
0 -1.97 1.18 -1.03
1 -0.45 0.66 -0.59
2 -0.31 0.40 -0.66
3 -0.05 0.11 -1.71
回顾:map(函数名,序列)的作用是对序列中的每一个元素调用指定函数
applymap函数存在是因为Series有map方法
In [165]: df4[1]
Out[165]:
0 1.182724
1 0.656434
2 0.398418
3 0.114076
Name: 1, dtype: float64
In [166]: df4[1].map(lambda x:'%.2f' % x)
Out[166]:
0 1.18
1 0.66
2 0.40
3 0.11
Name: 1, dtype: object
Series的map函数还可以传入一个字典,表示将Series中的每个元素当做字典的键,在字典中查询相应的值
In [50]: data = 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]})
...:
In [51]: data
Out[51]:
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
In [52]: meat_to_animal = {
...: 'bacon': 'pig',
...: 'pulled pork': 'pig',
...: 'pastrami': 'cow',
...: 'corned beef': 'cow',
...: 'honey ham': 'pig',
...: 'nova lox': 'salmon'
...: }
In [53]:
In [53]: lowercased = data['food'].str.lower()
...:
...: lowercased
...: data['animal'] = lowercased.map(meat_to_animal)#此处map函数传入的是一个字典
...: data
...:
...:
Out[53]:
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.9 排序和排名
1.9.1 排序
-
df.sort_index(axis, ascending)
- axis:在哪个周上面排序
- ascending:是否是升序
In [167]: frame = pd.DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c']) In [168]: frame.sort_index() Out[168]: d a b c one 4 5 6 7 three 0 1 2 3 In [169]: frame.sort_index(axis='columns')#axis='columns'等价于axis=1 Out[169]: a b c d three 1 2 3 0 one 5 6 7 4 In [170]: frame.sort_index(axis='columns',ascending=False) Out[170]: d c b a three 0 3 2 1 one 4 7 6 5
-
df.sort_values(by)
默认是升序,在升序情况下,缺失值会被排到Series尾部
对于Series来说不需要by参数,但对于DataFrame来说,by参数必不可少
In [171]: frame Out[171]: d a b c three 0 1 2 3 one 4 5 6 7 In [172]: frame.sort_values(axis=1,ascending=False) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-172-eaa4efc29b60> in <module>() ----> 1 frame.sort_values(axis=1,ascending=False) TypeError: sort_values() missing 1 required positional argument: 'by' In [173]: frame.sort_values(axis=1,ascending=False,by='three') Out[173]: c b a d three 3 2 1 0 one 7 6 5 4
还可以给by参数传递一个列表
1.9.2 排名
rank(axis,ascending,method)
- axis:在那个轴上面排名
- ascending:是否是升序
- method:如何分配平级关系
- ‘average’:默认的,使用每个组中分配平均排名
- ‘min’:对整个组使用最小排名
- ‘max’:对整个组使用最大排名
- ‘first’:按照值在数据中出现的次序分配排名
- ‘dense’:类似于method=‘first’,但组间排名总是增加1,而不是一个组中相等的元素数量
1.10 描述性统计的概述与计算
与Numpy中的统计方法类似,但是不同的是,pandas中内建了处理缺失值的功能
除非整行或整列都是NA,否则NA值是被自动排除的,可以通过skipna(bool)参数来实现不排除NA值
In [179]: df
Out[179]:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
In [180]: df.sum(axis='columns')
Out[180]:
a 1.40
b 2.60
c 0.00
d -0.55
dtype: float64
In [181]: df.sum(axis='columns',skipna=False)
Out[181]:
a NaN
b 2.60
c NaN
d -0.55
dtype: float64
其他常用统计方法
- idxmin()和idxmax()返回的是最小值和最大值的索引值
- cumsum()累计求和
- describe()产生多个汇总统计,对于非数值型数据,describe()方法产生另一种汇总统计
- count()非NA值的个数
- argmin(),argmax()最小值和最大值的索引值的位置(整数)
- quantile()计算样本的从0到1间的分位数
- median()中位数
- prod()所有值的积
- var()
- std()
- 其他
相关性和协方差
- corr()相关系数
- cov()协方差
In [182]: df4
Out[182]:
0 1 2
0 -1.971583 1.182724 -1.030719
1 -0.450175 0.656434 -0.594173
2 -0.310988 0.398418 -0.659847
3 -0.054048 0.114076 -1.713716
In [183]: df4.corr()
Out[183]:
0 1 2
0 1.000000 -0.948712 -0.141207
1 -0.948712 1.000000 0.404908
2 -0.141207 0.404908 1.000000
In [184]: df4.cov()
Out[184]:
0 1 2
0 0.749292 -0.373008 -0.062753
1 -0.373008 0.206308 0.094421
2 -0.062753 0.094421 0.263578
In [185]: df4[0].corr(df4[1])
Out[185]: -0.9487122337221459
In [186]: df4[0].cov(df4[1])
Out[186]: -0.37300831221892944
In [187]: df4.corrwith(df4[0])
Out[187]:
0 1.000000
1 -0.948712
2 -0.141207
dtype: float64
1.11 唯一值、计数和成员属性
-
series.unique()
In [188]: obj = pd.Series(['c','a','d','a','a','b','b','c','c']) In [189]: obj.unique() Out[189]: array(['c', 'a', 'd', 'b'], dtype=object)
-
series.values_count()计数
In [190]: obj.value_counts()#会自动将结果降序排列 Out[190]: a 3 c 3 b 2 d 1 dtype: int64
-
pd.values_count(series,sort:bool)
In [192]: pd.value_counts(obj,sort=False) Out[192]: b 2 c 3 a 3 d 1 dtype: int64
-
isin()执行向量化成员属性检查
In [194]: obj.isin(['b','c']) Out[194]: 0 True 1 False 2 False 3 False 4 False 5 True 6 True 7 True 8 True dtype: bool
举例:
In [8]: data = pd.DataFrame({'Qu1':[1,3,4,3,4],'Qu2':[2,3,1,2,3],'Qu3':[1,5,2,4,4]}) In [9]: data Out[9]: Qu1 Qu2 Qu3 0 1 2 1 1 3 3 5 2 4 1 2 3 3 2 4 4 4 3 4 In [10]: data.apply(pd.value_counts).fillna(0) Out[10]: Qu1 Qu2 Qu3 1 1.0 1.0 1.0 2 0.0 2.0 1.0 3 2.0 2.0 0.0 4 2.0 0.0 2.0 5 0.0 0.0 1.0