美文网首页Python Pandas
12-12 第五章 01 pandas 入门 5.1panda

12-12 第五章 01 pandas 入门 5.1panda

作者: 渔家傲_俞 | 来源:发表于2018-12-13 21:05 被阅读0次

    pandas是本书后续内容的首选库。
    它含有使数据清洗和分析工作变得更快更简单的数据结构和操作工具。pandas经常和其它工具一同使用,如数值计算工具NumPy和SciPy,分析库statsmodels和scikit-learn,和数据可视化库matplotlib。pandas是基于NumPy数组构建的,特别是基于数组的函数和不使用for循环的数据处理。
    http://nbviewer.jupyter.org/github/LearnXu/pydata-notebook/tree/master/
    虽然pandas采用了大量的NumPy编码风格,但二者最大的不同是pandas是专门为处理表格和混杂数据设计的。而NumPy更适合处理统一的数值数组数据。
    自从2010年pandas开源以来,pandas逐渐成长为一个非常大的库,应用于许多真实案例。开发者社区已经有了800个独立的贡献者,他们在解决日常数据问题的同时为这个项目提供贡献。
    在本书后续部分中,我将使用下面这样的pandas引入约定:

    In [1]: import pandas as pd
    

    因此,只要你在代码中看到pd.,就得想到这是pandas。因为Series和DataFrame用的次数非常多,所以将其引入本地命名空间中会更方便:

    In [2]: from pandas import Series, DataFrame
    

    5.1 pandas的数据结构介绍

    数据结构其实就是Series和DataFrame。

    1 Series

    Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的index(即索引)组成。仅由一组数据即可产生最简单的Series:

    In [11]: obj = pd.Series([4, 7, -5, 3])
    
    In [12]: obj
    Out[12]: 
    0    4
    1    7
    2   -5
    3    3 #前面一列就是索引
    dtype: int64
    

    可以看到,左边表示index,右边表示对应的value。可以通过value和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)
    

    当然我们也可以自己指定index的label:

    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')
    

    可以用index的label来选择:

    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
    

    这里['c', 'a', 'd']其实被当做了索引,尽管这个索引是用string构成的。

    使用numpy函数或类似的操作,会保留index-value的关系:

    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
    

    另一种看待series的方法,它是一个长度固定,有顺序的dict,从index映射到value。在很多场景下,可以当做dict来用:

    In [24]: 'b' in obj2
    Out[24]: True
    
    In [25]: 'e' in obj2
    Out[25]: False
    

    还可以直接用现有的dict来创建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中的index其实就是dict中排好序的keys。我们也可以传入一个自己想要的顺序:

    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索引相匹配的那3个值会被找出来并放到相应的位置上,但由于"California"所对应的sdata值找不到,所以其结果就为NaN(即“非数字”(not a number),在pandas中,它用于表示缺失或NA值)。因为‘Utah’不在states中,它被从结果中除去。
    我将使用缺失(missing)或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也有类似的实例方法:

    In [34]: obj4.isnull()
    Out[34]: 
    California     True
    Ohio          False
    Oregon        False
    Texas         False
    dtype: bool
    

    关于缺失数据,在第七章还会讲得更详细一些。

    series中一个有用的特色自动按index label来排序(Data alignment features):

    In [35]: obj3
    Out[35]: 
    Ohio      35000
    Oregon    16000
    Texas     71000
    Utah       5000
    dtype: int64
    
    In [36]: obj4
    Out[36]: 
    California        NaN
    Ohio          35000.0
    Oregon        16000.0
    Texas         71000.0
    dtype: float64
    
    In [37]: obj3 + obj4
    Out[37]: 
    California         NaN
    Ohio           70000.0
    Oregon         32000.0
    Texas         142000.0
    Utah               NaN
    dtype: float64
    

    这个Data alignment features(数据对齐特色)和数据库中的join相似。

    serice自身和它的index都有一个叫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的index能被直接更改:

    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
    

    2 DataFrame

    DataFrame表示一个长方形表格,并包含排好序的列,每一列都可以是不同的数值类型(数字,字符串,布尔值)。DataFrame有行索引和列索引(row index, column index);可以看做是分享所有索引的由series组成的字典。数据是保存在一维以上的区块里的。
    (其实我是把dataframe当做excel里的那种表格来用的,这样感觉更直观一些)
    构建一个dataframe的方法,用一个dcit,dict里的值是list:

    In [2]: import pandas as pd
    In [3]:  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)
       ...:
       ...: frame
       ...:
    Out[3]: #结果DataFrame会自动加上索引(跟Series一样),且全部列会被有序排列
        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方法会返回前5行(注:这个函数在数据分析中经常使用,用来查看表格里有什么东西):

    In [46]: frame.head()
    Out[46]: 
       pop   state  year
    0  1.5    Ohio  2000
    1  1.7    Ohio  2001
    2  3.6    Ohio  2002
    3  2.4  Nevada  2001
    4  2.9  Nevada  2002
    

    如果指定一列的话,会自动按列排序:

    In [47]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
    Out[47]: 
       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 [48]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
       ....:                       index=['one', 'two', 'three', 'four',
       ....:                              'five', 'six'])
    
    In [49]: frame2
    Out[49]: 
           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
    
    In [50]: frame2.columns
    Out[50]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
    

    从DataFrame里提取一列的话会返回series格式,可以以属性或是dict一样的形式来提取:

    In [51]: frame2['state']
    Out[51]: 
    one        Ohio
    two        Ohio
    three      Ohio
    four     Nevada
    five     Nevada
    six      Nevada
    Name: state, dtype: object
    
    In [52]: frame2.year
    Out[52]: 
    one      2000
    two      2001
    three    2002
    four     2001
    five     2002
    six      2003
    Name: year, dtype: int64
    

    笔记:frame2[column]适用于任何列的名,但是frame2.column只有在列名存在才适用。
    返回的series有DataFrame种同样的index,而且name属性也是对应的。

    对于行,要用在loc属性里用 位置或名字(就第几行:

    In [53]: frame2.loc['three']
    Out[53]: 
    year     2002
    state    Ohio
    pop       3.6
    debt      NaN
    Name: three, dtype: object
    

    列值也能通过赋值改变。比如给debt赋值:

    In [54]: frame2['debt'] = 16.5
    
    In [55]: frame2
    Out[55]: 
           year   state  pop  debt
    one    2000    Ohio  1.5  16.5
    two    2001    Ohio  1.7  16.5
    three  2002    Ohio  3.6  16.5
    four   2001  Nevada  2.4  16.5
    five   2002  Nevada  2.9  16.5
    six    2003  Nevada  3.2  16.5
    
    In [56]: frame2['debt'] = np.arange(6.)
    
    In [57]: frame2
    Out[57]: 
           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
    

    如果把list或array赋给column的话,长度必须符合DataFrame的长度。如果把一二series赋给DataFrame,会按DataFrame的index来赋值,不够的地方用缺失数据来表示:

    In [58]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
    
    In [59]: frame2['debt'] = val
    
    In [60]: frame2
    Out[60]: 
           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也能像删除字典关键字一样,删除列:

    In [61]: frame2['eastern'] = frame2.state == 'Ohio'
    
    In [62]: frame2
    Out[62]: 
           year   state  pop  debt  eastern
    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
    

    然后用del删除这一列:

    In [63]: del frame2['eastern']
    
    In [64]: frame2.columns
    Out[64]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
    

    注意:columns返回的是一个view,而不是新建了一个copy。因此,任何对series的改变,会反映在DataFrame上。除非我们用copy方法来新建一个。

    另一种常见的格式是dict中的dict:

    In [65]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
    ....:        'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
    

    把上面这种嵌套dcit传给DataFrame,pandas会把外层dcit的key当做列,内层key当做行索引:

    In [66]: frame3 = pd.DataFrame(pop)
    
    In [67]: frame3
    Out[67]: 
          Nevada  Ohio
    2000     NaN   1.5
    2001     2.4   1.7
    2002     2.9   3.6
    

    你也可以使用类似NumPy数组的方法,对DataFrame进行转置(交换行和列):

    In [68]: frame3.T
    Out[68]: 
            2000  2001  2002
    Nevada   NaN   2.4   2.9
    Ohio     1.5   1.7   3.6
    

    指定index:

    In [69]: pd.DataFrame(pop, index=[2001, 2002, 2003])
    Out[69]: 
          Nevada  Ohio
    2001     2.4   1.7
    2002     2.9   3.6
    2003     NaN   NaN
    

    series组成的dict:

    In [70]: pdata = {'Ohio': frame3['Ohio'][:-1],
    ....:          'Nevada': frame3['Nevada'][:2]}
    
    In [71]: pd.DataFrame(pdata)
    Out[71]: 
          Nevada  Ohio
    2000     NaN   1.5
    2001     2.4   1.7
    

    表5-1列出了DataFrame构造函数所能接受的各种数据。


    DataFrame

    如果设置了DataFrame的index和columns的name属性,则这些信息也会被显示出来:

    In [72]: frame3.index.name = 'year'; frame3.columns.name = 'state'
    
    In [73]: frame3
    Out[73]: 
    state  Nevada  Ohio
    year
    2000      NaN   1.5
    2001      2.4   1.7
    2002      2.9   3.6
    

    values属性会返回二维数组:

    In [74]: frame3.values
    Out[74]: 
    array([[ nan,  1.5],
           [ 2.4,  1.7],
           [ 2.9,  3.6]])
    

    如果column有不同的类型,dtype会适应所有的列(如果DataFrame各列的数据类型不同,则值数组的dtype就会选用能兼容所有列的数据类型:

    In [75]: frame2.values
    Out[75]:
    array([[2000, 'Ohio', 1.5, nan],
           [2001, 'Ohio', 1.7, -1.2],
           [2002, 'Ohio', 3.6, nan],
           [2001, 'Nevada', 2.4, -1.5],
           [2002, 'Nevada', 2.9, -1.7],
           [2003, 'Nevada', 3.2, nan]], dtype=object)
    

    3 Index Objects (索引对象)

    pandas的Index Objects (索引对象)负责保存axis labels和其他一些数据(比如axis name或names)。一个数组或其他一个序列标签,只要被用来做构建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 object是不可更改的:

    In [3]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
    
    In [4]: index = obj.index
    
    In [5]: index[1] = 'd'
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-5-a452e55ce13b> in <module>()
    ----> 1 index[1] = 'd'
    
    C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
       2063
       2064     def __setitem__(self, key, value):
    -> 2065         raise TypeError("Index does not support mutable operations")
       2066
       2067     def __getitem__(self, key):
    
    TypeError: Index does not support mutable operations
    

    正因为不可修改,所以data structure中分享index object是很安全的:

    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
    

    注意:虽然用户不需要经常使用Index的功能,但是因为一些操作会生成包含被索引化的数据,理解它们的工作原理是很重要的。
    index除了像数组,还能像大小一定的set——set是一个无序且不重复的元素集合。(除了类似于数组,Index的功能也类似一个固定大小的集合:

    In [85]: frame3
    Out[85]: 
    state  Nevada  Ohio
    year               
    2000      NaN   1.5
    2001      2.4   1.7
    2002      2.9   3.6
    In [86]: frame3.columns
    Out[86]: Index(['Nevada', 'Ohio'], dtype='object', name='state')
    
    In [87]: 'Ohio' in frame3.columns
    Out[87]: True
    
    In [88]: 2003 in frame3.index
    Out[88]: False
    

    与python里的set不同,pandas的index可以有重复的labels:

    In [89]: dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
    
    In [90]: dup_labels
    Out[90]: Index(['foo', 'foo', 'bar', 'bar'], dtype='object')
    

    在这种重复的标签中选择的话,会选中所有相同的标签。

    Index还有一些方法和属性:


    index方法和属性

    相关文章

      网友评论

        本文标题:12-12 第五章 01 pandas 入门 5.1panda

        本文链接:https://www.haomeiwen.com/subject/sokuhqtx.html