美文网首页我爱编程
【Chapter 5.1】Pandas的数据结构

【Chapter 5.1】Pandas的数据结构

作者: 蜘蛛的梦呓 | 来源:发表于2018-05-23 14:47 被阅读0次

    【Chapter 5 pandas 入门】

    pandas是基于NumPy数组构建的,特别是基于数组的函数和不使用for循环的数据处理。

    import pandas
    from test_pandas import  Series,DataFrame
    

    5.1 pandas 的数据结构

    要使用pandas,你首先就得熟悉它的两个主要数据结构:Series和DataFrame。虽然它们并不能解决所有问题,但它们为大多数应用提供了一种可靠的、易于使用的基础。

    1. Series

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

    import pandas as pd
    
    from pandas import Series, DataFrame
    
    obj=pd.Series([4,7,-5,3])
    
    obj
    Out[10]: 
    0    4
    1    7
    2   -5
    3    3
    dtype: int64
    

    Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。你可以通过Series 的values和index属性获取其数组表示形式和索引对象:

    obj.values
    Out[11]: array([ 4,  7, -5,  3], dtype=int64)
    
    obj.index
    Out[12]: RangeIndex(start=0, stop=4, step=1)
    
    #通常,我们希望所创建的Series带有一个可以对各个数据点进行标记的索引:
    
    obj2 = pd.Series([4,7,-5,3],index=['d','b','a','c'])
    
    obj2
    Out[16]: 
    d    4
    b    7
    a   -5
    c    3
    dtype: int64
    

    与普通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
    

    ['c', 'a', 'd']是索引列表,即使它包含的是字符串而不是整数。

    使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接:

    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)#Exp:返回e的n次方,e是一个常数为2.71828
    Out[23]: 
    d     403.428793
    b    1096.633158
    a       0.006738
    c      20.085537
    dtype: float64
    
    

    还可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中:

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

    如果数据被存放在一个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
    
    

    如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。你可以传入排好序的字典的键以改变顺序:

    states = ['California', 'Ohio', 'Oregon', 'Texas','Utah']
    
    obj = pd.Series(sdata,index=states)
    
    obj
    Out[41]: 
    California        NaN
    Ohio          35000.0
    Oregon        16000.0
    Texas         71000.0
    Utah           5000.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最重要的一个功能是,它会根据运算的索引标签自动对齐数据:

    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
    

    数据对齐功能将在后面详细讲解。如果你使用过数据库,你可以认为是类似join的操作。

    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的索引可以通过赋值的方式就地修改:

    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
    

    2 DataFrame

    DataFrame表示一个长方形表格,并包含排好序的列,每一列都可以是不同的数值类型(数字,字符串,布尔值)。DataFrame有行索引和列索引(row index, column index);可以看做是分享所有索引的由series组成的字典。数据是保存在一维以上的区块里的。

    (其实我是把dataframe当做excel里的那种表格来用的,这样感觉更直观一些)

    建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典:

    
    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 #结果DataFrame会自动加上索引(跟Series一样),且全部列会被有序排列:
    
    Out[44]: 
       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
    5  3.2  Nevada  2003
    

    对于特别大的DataFrame,head方法会选取前五行:

    frame.head()
    Out[45]: 
       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
    

    如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列:

    pd.DataFrame(data,columns=['year','state','pop'])
    Out[46]: 
       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
    

    如果你导入一个不存在的列名,那么会显示为缺失数据:

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

    通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series:

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

    笔记:IPython提供了类似属性的访问(即frame2.year)和tab补全。 frame2[column]适用于任何列的名,但是frame2.column只有在列名是一个合理的Python变量名时才适用。

    注意,返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应地设置好了。

    行也可以通过位置或名称的方式进行获取,比如用loc属性(稍后将对此进行详细讲解):

    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
    
    

    将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值:

    val = pd.Series([-1.2,-1.5,-1.7],index=['two','four','five'])
    
    frame2['debt'] = val
    
    frame2
    Out[63]: 
           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 [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
    

    注意:不能用frame2.eastern创建新的列。

    del方法可以用来删除这列:

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

    注意:通过索引方式返回的列只是相应数据的视图而已,并不是副本。因此,对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Series的copy方法即可指定复制列。

    另一种常见的数据形式是嵌套字典:

    pop = {'Nevada': {2001: 2.4, 2002: 2.9},
           'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
           
    frame3 = pd.DataFrame(pop)
    
    frame3
    Out[74]: 
          Nevada  Ohio
    2000     NaN   1.5
    2001     2.4   1.7
    2002     2.9   3.6
    

    另外DataFrame也可以向numpy数组一样做转置:

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

    内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引,则不会这样:

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

    由Series组成的字典差不多也是一样的用法:

    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的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
    
    

    3. 索引对象

    pandas的Index Objects (索引对象)负责保存axis labels和其他一些数据(比如axis name或names)。一个数组或其他一个序列标签,只要被用来做构建series或DataFrame,就会被自动转变为index:

    obj = pd.Series(range(3),index = ['a','b','c'])
    
    index = obj.index
    
    index
    Out[84]: Index(['a', 'b', 'c'], dtype='object')
    
    index[1:]
    Out[85]: Index(['b', 'c'], dtype='object')
    

    Index对象是不可变的,因此用户不能对其进行修改:

    idnex[1:]
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-87-064d000c2ca0> in <module>()
    ----> 1 idnex[1:]
    
    NameError: name 'idnex' is not defined
    

    不可变可以使Index对象在多个数据结构之间安全共享:

    labels = pd.Index(np.arange(3))
    
    labels
    Out[89]: Int64Index([0, 1, 2], dtype='int64')
    
    obj2 = pd.Series([1.5,-2.5,0],index=labels)
    
    obj2
    Out[91]: 
    0    1.5
    1   -2.5
    2    0.0
    dtype: float64
    
    obj2.index is labels
    Out[92]: True
    

    注意:虽然用户不需要经常使用Index的功能,但是因为一些操作会生成包含被索引化的数据,理解它们的工作原理是很重要的。

    除了类似于数组,Index的功能也类似一个固定大小的集合:

    frame3
    Out[94]: 
    state  Nevada  Ohio
    year               
    2000      NaN   1.5
    2001      2.4   1.7
    2002      2.9   3.6
    
    frame3.columns
    Out[95]: Index(['Nevada', 'Ohio'], dtype='object', name='state')
    
    'Ohio' in frame3.columns
    Out[96]: True
    
    2003 in frame3.index
    Out[97]: False
    

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

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

    选择重复的标签,会显示所有的结果。

    每个索引都有一些方法和属性,它们可用于设置逻辑并回答有关该索引所包含的数据的常见问题。表5-2列出了这些函数。

    相关文章

      网友评论

        本文标题:【Chapter 5.1】Pandas的数据结构

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