经过前面几个章节的衬托,咱们关于数据处理也有了一点了解。后续首要首选是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列出了索引常见的办法和特点

啃书:《利用python进行数据分析》第五章——pandas入门(一)

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进行了总结。后面会看到,还有更多的办法进行层级化索引。

啃书:《利用python进行数据分析》第五章——pandas入门(一)

图5-1 DataFrame的常用索引选项

由于内容太多这儿分一篇!!