啃书:《利用python进行数据分析》第五章——pandas入门(一)
经过前面几个章节的衬托,咱们关于数据处理也有了一点了解。后续首要首选是Pandas,它包括了使数据清洗和分析工作更快更简单的数据结构和操作东西。pandas经常会和其他东西一同并行运用,如上章学习到的numpy和scipy,分析库statsmodels和scikit-learn,和数据可视化库matplotlib。pandas是依据numpy建立的,特别是对依据数组的函数和不运用for循环的数据处理。
尽管pandas运用了很多的numpy编码风格,可是二者最大的不同是pandas专门为处理表格和混杂数据设计的框架。而numpy愈加合适处理一致的数值数组数据。
本章中,我将运用以下约定引进pandas:
In [1]: import pandas as pd
因为Series和DataFrame用的次数十分多,所以将其引进本地命名空间中会更便利:
In [2]: from pandas import Series, DataFrame
5.1pandas的数据结构
要运用pandas,你首要就得熟悉它的两个首要数据结构:Series和DataFrame。这两个基本数可以解决大多数的处理问题了,所以咱们要了解清楚他们的细节。
Series
Series是一种相似一维数组的目标,它是由一组数据(各种numpy的数据类型)以及一组与之相关的数据标签(索引)组成。
In [11]: obj = pd.Series([4, 7, -5, 3])
In [12]: obj
Out[12]:
0 4
1 7
2 -5
3 3
dtype: int64
Series的表现方式是左边是索引,右边是数据值。这儿咱们并没有对数据进行特殊索引设置,所以是默许从0开端的索引标号。你也可以经过Series的values和index特点对数组内容进行访问:
In [13]: obj.values
Out[13]: array([ 4, 7, -5, 3])
In [14]: obj.index # like range(4)
Out[14]: RangeIndex(start=0, stop=4, step=1)
通常来说,咱们希望Series可以对各个数据进行标记:
In [15]: obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
In [16]: obj2
Out[16]:
d 4
b 7
a -5
c 3
dtype: int64
In [17]: obj2.index
Out[17]: Index(['d', 'b', 'a', 'c'], dtype='object')
与一般NumPy数组比较,你可以经过索引的办法选取Series中的单个或一组值:
In [18]: obj2['a']
Out[18]: -5
In [19]: obj2['d'] = 6
In [20]: obj2[['c', 'a', 'd']]
Out[20]:
c 3
a -5
d 6
dtype: int64
当然你也可以经过上章节所学的numpy的相关知识对Series进行数据运算:
In [21]: obj2[obj2 > 0]
Out[21]:
d 6
b 7
c 3
dtype: int64
In [22]: obj2 * 2
Out[22]:
d 12
b 14
a -10
c 6
dtype: int64
In [23]: np.exp(obj2)
Out[23]:
d 403.428793
b 1096.633158
a 0.006738
c 20.085537
dtype: float64
假如数据被存放在一个Python字典中,也可以直接经过这个字典来创立Series:
In [26]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
In [27]: obj3 = pd.Series(sdata)
In [28]: obj3
Out[28]:
Ohio 35000
Oregon 16000
Texas 71000
Utah 5000
dtype: int64
假如只传入一个字典,则成果Series中的索引便是原字典的键(有序摆放)。你可以传入排好序的字典的键以改变次序:
In [29]: states = ['California', 'Ohio', 'Oregon', 'Texas']
In [30]: obj4 = pd.Series(sdata, index=states)
In [31]: obj4
Out[31]:
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64
这个例子中,sdata和states索引相匹配的才会存入新生成的目标中,由于states中的California
找不到对应值,所以为NaN。而Utah
并不在states中,所以也不存在。
这种NaN在pandas中被称为丢失值或NA值。pandas有函数isnull和notnull进行检测数组中是否含有丢失值:
In [32]: pd.isnull(obj4)
Out[32]:
California True
Ohio False
Oregon False
Texas False
dtype: bool
In [33]: pd.notnull(obj4)
Out[33]:
California False
Ohio True
Oregon True
Texas True
dtype: bool
当然仔细的同学或许发现了Series很重要的功用便是数据对齐,数据可以很整齐的摆放,这对咱们数据分析有很大帮助。Series目标自身和其索引都有一个特点name,该特点和pandas的其他功用密切相关:
In [38]: obj4.name = 'population'
In [39]: obj4.index.name = 'state'
In [40]: obj4
Out[40]:
state
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
Name: population, dtype: float64
同时Series的索引可以经过赋值就地修改:
In [41]: obj
Out[41]:
0 4
1 7
2 -5
3 3
dtype: int64
In [42]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
In [43]: obj
Out[43]:
Bob 4
Steve 7
Jeff -5
Ryan 3
dtype: int64
DataFrame
DataFrame是一个表格型数据结构,它含有一组有序列,每列可以识不同类型值。DataFrame既有行索引,也有列索引,它可以被看成是Series组成的字典。DataFrame中的数据是以一个或多个二维块存放的,而不是列表,字典或者其他的一维数组的调集。关于其内部完成,这超出了本章的范围,所以有兴趣的小伙伴可以自行查阅了解细节。
学一个新的数据结构首要便是要学会它怎么结构。有很多办法都可以结构DataFrame,最常用的办法便是运用包括等长度列表或Numpy数组的字典来构成DataFrame:
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002, 2003],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)
成果DataFrame会主动加上索引(跟Series一样):
In [24]:frame
Out[24]:
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
5 Nevada 2003 3.2
假如你运用的是Jupyter notebook,pandas DataFrame目标会以对浏览器友好的HTML表格的办法呈现。 关于特别大的DataFrame,head办法会选取前五行:
In [26]:frame.head()
Out[27]:
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
假如你想要自定义列序,你需求制定好序列次序:
In [27]:pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[28]:
year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2
假如传入的列在数据中找不到,就会在成果中产生缺失值:
In [28]:pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
....: index=['one', 'two', 'three', 'four',
....: 'five', 'six'])
Out[29]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 NaN
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 NaN
five 2002 Nevada 2.9 NaN
six 2003 Nevada 3.2 NaN
经过相似字典标记的办法或特点的办法,可以将DataFrame的列获取为一个Series:
In [36]:frame2['year']
Out[33]:
one 2000
two 2001
three 2002
four 2001
five 2002
six 2003
Name: year, dtype: int64
In [36]:frame2.state
Out[34]:
one Ohio
two Ohio
three Ohio
four Nevada
five Nevada
six Nevada
Name: state, dtype: object
行也可以经过方位或称号办法进行获取,比方用到loc特点:
In [36]:frame2.loc['three']
Out[36]:
year 2002
state Ohio
pop 3.6
debt NaN
Name: three, dtype: object
列可以经过赋值的办法进行修改。例如,咱们可以给那个空的”debt”列赋上一个标量值或一组值:
In [37]: frame2['debt'] = 16
In [38]:frame2
Out[38]:
year state pop debt
one 2000 Ohio 1.5 16
two 2001 Ohio 1.7 16
three 2002 Ohio 3.6 16
four 2001 Nevada 2.4 16
five 2002 Nevada 2.9 16
six 2003 Nevada 3.2 16
In [39]: import numpy as np
In [40]: frame2['debt'] = np.arange(6.)
In [41]: frame2
Out[41]:
year state pop debt
one 2000 Ohio 1.5 0.0
two 2001 Ohio 1.7 1.0
three 2002 Ohio 3.6 2.0
four 2001 Nevada 2.4 3.0
five 2002 Nevada 2.9 4.0
six 2003 Nevada 3.2 5.0
将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。假如赋值的是一个Series,就会精确匹配DataFrame的索引,一切的空位都将被填上缺失值:
In [42]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
In [43]: frame2['debt'] = val
In [44]: frame2
Out[44]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 -1.2
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 -1.5
five 2002 Nevada 2.9 -1.7
six 2003 Nevada 3.2 NaN
为不存在的列赋值会创立出一个新列。关键字del用于删去列。作为del的例子,我先添加一个新的布尔值的列,state是否为’Ohio’:
In [45]: frame2['ear'] = frame2.state == 'Ohio'
In [46]: frame2
Out[46]:
year state pop debt ear
one 2000 Ohio 1.5 NaN True
two 2001 Ohio 1.7 -1.2 True
three 2002 Ohio 3.6 NaN True
four 2001 Nevada 2.4 -1.5 False
five 2002 Nevada 2.9 -1.7 False
six 2003 Nevada 3.2 NaN False
注意这儿不能用frame2.eastern创立新的列。
del办法可以用来删去这列:
In [47]: del frame2['ear']
In [48]: frame2.columns
Out[48]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
注意:经过索引办法回来的列仅仅相应数据的视图罢了,并不是副本。因此,对回来的Series所做的任何就地修改全都会反映到源DataFrame上。经过Series的copy办法即可指定复制列。
另一种常见的数据方式是嵌套字典:
In [49]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
....: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
假如嵌套字典传给DataFrame,pandas就会被解释为:外层字典的键作为列,内层键则作为行索引:
In [50]: frame3 = pd.DataFrame(pop)
In [51]: frame3
Out[52]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
你也可以运用相似NumPy数组的办法,对DataFrame进行转置(交换行和列):
In [53]: frame3.T
Out[53]:
2000 2001 2002
Nevada NaN 2.4 2.9
Ohio 1.5 1.7 3.6
索引目标
pandas的索引目标担任办理轴标签和其他的元数据(例如轴称号)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换为Index:
In [76]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
In [77]: index = obj.index
In [78]: index
Out[78]: Index(['a', 'b', 'c'], dtype='object')
In [79]: index[1:]
Out[79]: Index(['b', 'c'], dtype='object')
Index目标是不可变的,因此用户不能对其进行修改。不可变可以使Index目标在多个数据结构之间安全共享:
In [80]: labels = pd.Index(np.arange(3))
In [81]: labels
Out[81]: Int64Index([0, 1, 2], dtype='int64')
In [82]: obj2 = pd.Series([1.5, -2.5, 0], index=labels)
In [83]: obj2
Out[83]:
0 1.5
1 -2.5
2 0.0
dtype: float64
In [84]: obj2.index is labels
Out[84]: True
下图表5-2列出了索引常见的办法和特点
5.2基本功用
根底概念介绍完毕了,接下来要对数据操作的基本手法进行一个解决,本文并不是罗列一切的pandas库,所以只展示一些常用函数,假如要深入学习,可以自己仔细阅读相关文档进一步学习。
重建索引
reindex是pandas目标的重要办法,该办法用于创立一个符合新索引的新目标:
In [91]: obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
In [92]: obj
Out[92]:
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
用该Series的reindex将会依据新索引进行重排。假如某个索引值当前不存在,就引进缺失值:
In [93]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
In [94]: obj2
Out[94]:
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
关于次序结构的数据,比方递增函数,在重建索引的时分会需求进行插值和填充。method办法可以答应咱们对其刺进,例如ffill办法,会在值前刺进:
In [95]: obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
In [96]: obj3
Out[96]:
0 blue
2 purple
4 yellow
dtype: object
In [97]: obj3.reindex(range(6), method='ffill')
Out[97]:
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
在DataFrame中,reindex依然可以更改行与列的索引值。只需求传递一个序列,成果就会重置:
In [98]: frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
....: index=['a', 'c', 'd'],
....: columns=['Ohio', 'Texas', 'California'])
In [99]: frame
Out[99]:
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
In [100]: frame2 = frame.reindex(['a', 'b', 'c', 'd'])
In [101]: frame2
Out[101]:
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
列可以用columns关键字从头索引:
In [102]: states = ['Texas', 'Utah', 'California']
In [103]: frame.reindex(columns=states)
Out[103]:
Texas Utah California
a 1 NaN 2
c 4 NaN 5
d 7 NaN 8
轴向上删去条目
假如此时你已经拥有了索引数组或不含条目的列表,在轴向上删去一个或更多的条目就很容易,但这样需求一些数据操作和调集逻辑,drop办法会回来一个含有指示值或轴向上删去值的新目标:
In [105]: obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
In [106]: obj
Out[106]:
a 0.0
b 1.0
c 2.0
d 3.0
e 4.0
dtype: float64
In [107]: new_obj = obj.drop('c')
In [108]: new_obj
Out[108]:
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
In [109]: obj.drop(['d', 'c'])
Out[109]:
a 0.0
b 1.0
e 4.0
dtype: float64
在DataFrame中,有相似的特点办法,详细就不再演示了,我们可以自己测验。不过要当心运用drop函数中的inplace特点,当心运用inplace,它会毁掉一切被删去的数据。‘
索引、选取和过滤
Series的索引工作办法相似于Numpy,只不过Series有更丰富的索引类型:
In [117]: obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
In [118]: obj
Out[118]:
a 0.0
b 1.0
c 2.0
d 3.0
dtype: float64
In [119]: obj['b']
Out[119]: 1.0
In [120]: obj[1]
Out[120]: 1.0
In [121]: obj[2:4]
Out[121]:
c 2.0
d 3.0
dtype: float64
In [122]: obj[['b', 'a', 'd']]
Out[122]:
b 1.0
a 0.0
d 3.0
dtype: float64
In [123]: obj[[1, 3]]
Out[123]:
b 1.0
d 3.0
dtype: float64
In [124]: obj[obj < 2]
Out[124]:
a 0.0
b 1.0
dtype: float64
DataFrame的操作办法相似Series。相同可以经过上述办法进行挑选。这使得DataFrame的语法与NumPy二维数组的语法很像。
用loc和iloc进行选取
关于DataFrame的行标签,pandas引进了loc和iloc,它们可以让运用者可以经过相似与numpy的标记办法,运用轴标签(loc)或整数标签(iloc),从DataFrame挑选行和列的子集。以下作一个开始示例,咱们来经过标签挑选一行或多列:
In [137]: data.loc['Colorado', ['two', 'three']]
Out[137]:
two 5
three 6
Name: Colorado, dtype: int64
然后用iloc和整数进行选取,数字就代表行与列:
In [138]: data.iloc[2, [3, 0, 1]]
Out[138]:
four 11
one 8
two 9
Name: Utah, dtype: int64
In [139]: data.iloc[2]
Out[139]:
one 8
two 9
three 10
four 11
Name: Utah, dtype: int64
In [140]: data.iloc[[1, 2], [3, 0, 1]]
Out[140]:
four one two
Colorado 7 0 5
Utah 11 8 9
这两个索引函数也适用于一个标签或多个标签的切片。所以,在pandas中,有多个办法可以选取和从头组合数据。关于DataFrame,图5-1进行了总结。后面会看到,还有更多的办法进行层级化索引。
图5-1 DataFrame的常用索引选项由于内容太多这儿分一篇!!