美文网首页
pandas入门

pandas入门

作者: YuAllon | 来源:发表于2019-06-13 15:19 被阅读0次

    写在前面的话

    在做天文数据处理的过程中,基本上是和表格数据打交道,因此在处理天文数据的过程中pandas就是自己首选。利用pandas可以很方便的提取出自己想要的行或列的数据,方便自己后面做统计分析。因此,写一篇pandas入门的文章记录一下自己学习pandas的总结。

    推荐另外一篇pandas入门文档:10 Minutes to pandas

    pandas的功能

    1. 具备按轴自动或显式数据对齐功能的数据结构。这可以防止许多由于数据未对齐以及来自不同数据源(索引方式不同)的数据而导致的常见错误。
    2. 集成时间序列功能。
    3. 既能处理时间序列数据也能处理非时间序列数据的数据结构。
    4. 数学运算和约简(比如对某个轴求和)可以根据不同的元数据(轴号)执行。
    5. 灵活处理缺失数据。
    6. 合并及其他出现在常见数据库(例如基于SQL的)中的关系型运算。

    pandas引入约定

    import pandas as pd
    from pandas import Series,DataFrame
    

    pandas数据结构介绍

    要使用pandas,必须先要熟悉它的两个主要数据结构:SeriesData Frame

    Series

    Series是一种类似于一维数组的对象,它由一组数据和一组与之相关的数据标签(索引)组成。

    由一组数据生产简单的Series
    a = [1,3,'hello',4.5]
    b =pd.Series(a)
    print(b)
    0        1
    1        3
    2    hello
    3      4.5
    dtype: object
    

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

    b.values
    array([1, 3, 'hello', 4.6], dtype=object)
    b.index  #like range(4)
    RangeIndex(start=0, stop=4, step=1)
    

    通过索引可以获取对应的值:

    b[2]
    'hello'
    b[1:3]
    1        3
    2    hello
    dtype: object
    b[[1,2]]
    1        3
    2    hello
    dtype: object
    

    自定义索引:

    a = [1,3,'hello',4.5]
    c = pd.Series(a,index=[c,d,m,n])
    print(c)
    c        1
    d        3
    m    hello
    n      4.6
    dtype: object
    c['d']
    3
    c[['m','n']]
    m    hello
    n      4.6
    dtype: object
    

    使用Numpy函数或者Numpy的运算,都会保留索引值的链接:

    obj =pd.Series([1,5,7,3,2,-3])
    print(obj)
    0    1
    1    5
    2    7
    3    3
    4    2
    5   -3
    dtype: int64
    obj[obj<3]
    0    1
    4    2
    5   -3
    dtype: int64
    obj + 1
    0    2
    1    6
    2    8
    3    4
    4    3
    5   -2
    dtype: int64
    

    可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。

    print(c)
    c        1
    d        3
    m    hello
    n      4.6
    dtype: object
    'm' in c
    True
    's' in c
    False
    

    如果数据被存放在一个Python字典中,可以直接通过这个字典来创建Series。

    data = {'Tom':25,'Jerry':23,'Allon':26,'xiaoming':7}
    sdata = Series(data)
    sdata
    Tom         25
    Jerry       23
    Allon       26
    xiaoming     7
    dtype: int64
    

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

    name = ['Jerry','xiaoming','Tom','Bob']
    obj1 = Series(data,index=name)
    print(obj1)
    Jerry       23.0
    xiaoming     7.0
    Tom         25.0
    Bob          NaN
    dtype: float64
    

    由于'Bob'所对应的值找不到,所以就显示NAN(not a number),在pandas中NAN用于表示缺失或者NA值。由于'Allon'不在name中,所以它被从结果中除去。
    pandas中的isnullnotnull函数可用于检查缺失的数据:

    pd.isnull(obj1)
    Jerry       False
    xiaoming    False
    Tom         False
    Bob          True
    dtype: bool
    #Series也有类似的用法,是指已经导入Series函数
    obj1.isnull()
    Jerry       False
    xiaoming    False
    Tom         False
    Bob          True
    dtype: bool
    

    Series会根据运算的索引自动对齐数据(类似join操作):

    obj2 = Series({'a':4,'d':6,'k':8,'f':7})
    obj3 = Series({'d':1,'f':3,'a':6,'n':5})
    obj2 + obj3
    a    10.0
    d     7.0
    f    10.0
    k     NaN
    n     NaN
    dtype: float64
    

    Series的name属性,该属性与pandas其它关键功能关系密切:

    obj1
    Jerry       23.0
    xiaoming     7.0
    Tom         25.0
    Bob          NaN
    dtype: float64
    obj1.name = 'population'
    obj1.index.name = 'name'
    print(obj1)
    name
    Jerry       23.0
    xiaoming     7.0
    Tom         25.0
    Bob          NaN
    Name: population, dtype: float64
    

    Series的索引值可以通过赋值方式就地修改:

    obj2
    a    4
    d    6
    k    8
    f    7
    dtype: int64
    obj2.index = ['e','f','h','m']
    obj2
    e    4
    f    6
    h    8
    m    7
    dtype: int64
    

    DataFrame

    DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引。
    建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或Numpy数组组成的字典:

    data1 = {'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(data1)
    frame
       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
    

    我自己常用的构建DataFrame的方法:

    f = [8,5,3,7]
    m = [15,75,34,52]
    fm = pd.DataFrame([f,m])
    fm
        0   1   2   3
    0   8   5   3   7
    1   15  75  34  52
    

    没有索引(行or列),DataFrame会自动加上(跟Series一样)。
    对于特别大的DataFrame,head函数会选取前五行:

    frame.head()
        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
    

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

    pd.DataFrame(data1, columns=['year','pop','state'])
        year    pop state
    0   2000    1.5 Ohio
    1   2001    1.7 Ohio
    2   2002    3.6 Ohio
    3   2001    2.4 Nevada
    4   2002    2.9 Nevada
    5   2003    3.2 Nevada
    

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

    frame['pop']
    0    1.5
    1    1.7
    2    3.6
    3    2.4
    4    2.9
    5    3.2
    Name: pop, dtype: float64
    frame.year
    0    2000
    1    2001
    2    2002
    3    2001
    4    2002
    5    2003
    Name: year, dtype: int64
    

    提示:返回的Series拥有原DataFrame相同的索引,而且name属性也被相应的设置好了。

    行也可以通过位置或者名称进行获取,比如用loc属性

    frame
       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
    frame.loc[0]
    state    Ohio
    year     2000
    pop       1.5
    Name: 0, dtype: object
    

    列可以通过赋值的方式进行修改:

    frame['pop'] = 2.0
    frame
        state   year    pop
    0   Ohio    2000    2.0
    1   Ohio    2001    2.0
    2   Ohio    2002    2.0
    3   Nevada  2001    2.0
    4   Nevada  2002    2.0
    5   Nevada  2003    2.0
    

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

    #此例是直接添加某一列,当pop列本身存在时,就是赋值。
    frame['pop'] = np.arange(6.)
    frame
        state   year    pop
    0   Ohio    2000    0.0
    1   Ohio    2001    1.0
    2   Ohio    2002    2.0
    3   Nevada  2001    3.0
    4   Nevada  2002    4.0
    5   Nevada  2003    5.0
    #Series
    val = pd.Series([1.2,4.3,5.7], index=[0,3,5])
    frame['add'] = val
    frame
        state   year    pop add
    0   Ohio    2000    0.0 1.2
    1   Ohio    2001    1.0 NaN
    2   Ohio    2002    2.0 NaN
    3   Nevada  2001    3.0 4.3
    4   Nevada  2002    4.0 NaN
    5   Nevada  2003    5.0 5.7
    

    使用del函数可以删除某一列:

    del frame['pop']
    frame
        state   year
    0   Ohio    2000
    1   Ohio    2001
    2   Ohio    2002
    3   Nevada  2001
    4   Nevada  2002
    5   Nevada  2003
    

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

    data2 = {'Nevada':{2001:2.4, 2002:2.9},
            'Ohio':{2000:1.5, 2001:1.7, 2002:3.6}}
    frame1 = pd.DataFrame(data2)
    frame1
        Nevada  Ohio
    2000    NaN 1.5
    2001    2.4 1.7
    2002    2.9 3.6
    

    Tips:外层字典的键作为列,内层字典的键作为行索引。

    对DataFrame进行转值:

    frame1.T
           2000 2001 2002
    Nevada  NaN 2.4  2.9
    Ohio    1.5 1.7  3.6
    

    设置DataFrame的index和columns的name属性:

    frame1.index.name = 'year'
    frame1.columns.name = 'state'
    frame1
    state   Nevada  Ohio
    year        
    2000    NaN 1.5
    2001    2.4 1.7
    2002    2.9 3.6
    

    可以输入给DataFrame构造器的数据类型:

    Screen Shot 2019-06-13 at 16.22.31.png

    pandas基本功能

    本节介绍处理Series和DataFrame中的数据的基本手段,更详细的pandas库介绍可以看官网文档User_Guide

    重新索引

    pandas中的reindex是创建一个新的对象,使得数据符合新的索引。如果某个索引值当前不存在,则填入确实值。

    obj4 = pd.Series([4.5,7.2,-5.3,3.6], index=['d','b','a','c'])
    obj4
    d    4.5
    b    7.2
    a   -5.3
    c    3.6
    dtype: float64
    obj5 = obj4.reindex(['a','b','c','d','e'])
    obj5
    a   -5.3
    b    7.2
    c    3.6
    d    4.5
    e    NaN
    dtype: float64
    
    reindex函数的参数
    参数 说明
    index 用作索引的新序列
    method 插值(填充)方式,ffill or pad 向前填充值;bfill or backfill 向后填充值
    fill_value 引入缺失值时使用的替代值
    limit 向前或向后填充时的最大填充量
    tolerance 向前或向后填充时,填充不准确匹配项的最大间距(绝对距离)
    level 在Multilndex的指定级别上匹配简单索引,否则选取其子集
    copy 默认为True,无论如何都复制;如果为False,则新旧相等就不复制

    向前填充:

    obj6 = pd.Series(['blue', 'yellow', 'orange'],index=[0,2,4])
    obj6
    0      blue
    2    yellow
    4    orange
    dtype: object
    obj6.reindex(range(6),method='ffill')
    0      blue
    1      blue
    2    yellow
    3    yellow
    4    orange
    5    orange
    dtype: object
    

    列可以用columns关键字重新索引:

    frame2 = pd.DataFrame(np.arange(9).reshape((3,3),),
                         index=['a', 'c', 'd'],
                         columns=['Ohio', 'Texas', 'California'])
    frame2
        Ohio    Texas   California
    a   0       1       2
    c   3       4       5
    d   6       7       8
    states = ['Ohio', 'Utah', 'California']
    frame2.reindex(columns=states)
        Ohio    Utah    California
    a   0       NaN     2
    c   3       NaN     5
    d   6       NaN     8
    

    丢弃指定轴上的项drop函数

    obj6.drop(2)
    0      blue
    4    orange
    dtype: object
    #axis=0 or axis='rows'传递为行(默认);axis=1 or axis='columns'传递为列
    frame2.drop('Ohio', axis=1)
        Texas   California
    a   1       2
    c   4       5
    d   7       8
    #当drop函数中的参数设置为inplace=True时,就地修改对象,不会返回新的对象。必须要小心使用inplace,它会销毁所有被删除的数据
    

    索引、选取和过滤

    Series索引的工作方式类似于Numpy数组的索引,只不过Series的索引值不只是整数。

    obj5
    a   -5.3
    b    7.2
    c    3.6
    d    4.5
    e    NaN
    dtype: float64
    #利用标签切片运算与普通的Python的切片不同,其末端是包含的
    obj5['a':'c']
    a   -5.3
    b    7.2
    c    3.6
    dtype: float64
    #不用标签索切片时,与Python的切片相同
    obj5[:3]
    a   -5.3
    b    7.2
    c    3.6
    dtype: float64
    

    用一个值或序列对DataFrame进行索引其实就是获取一个或多个列:

    frame
        state   year    pop add
    0   Ohio    2000    0.0 1.2
    1   Ohio    2001    1.0 NaN
    2   Ohio    2002    2.0 NaN
    3   Nevada  2001    3.0 4.3
    4   Nevada  2002    4.0 NaN
    5   Nevada  2003    5.0 5.7
    frame[['state', 'pop']]
        state   pop
    0   Ohio    0.0
    1   Ohio    1.0
    2   Ohio    2.0
    3   Nevada  3.0
    4   Nevada  4.0
    5   Nevada  5.0
    frame[1:4]
        state   year    pop add
    1   Ohio    2001    1.0 NaN
    2   Ohio    2002    2.0 NaN
    3   Nevada  2001    3.0 4.3
    frame[frame['pop']>3]
        state   year    pop add
    4   Nevada  2002    4.0 NaN
    5   Nevada  2003    5.0 5.7
    

    用loc和iloc进行选

    对于DataFrame的行的标签索引,可以使用特殊的标签运算符轴标签loc和整数索引iloc。

    frame.loc[3,['state', 'pop']]
    state    Nevada
    pop           3
    Name: 3, dtype: object
    #iloc可以这样理解:不管有没有设置新的行或列索引,默认的索引都是存在的,而iloc就是提取默认的索引值。
    frame.iloc[3,[0,2]]
    state    Nevada
    pop           3
    Name: 3, dtype: object
    

    DataFrame数据选取与整合总结

    类型 说明
    df[val] 选取单列数据
    df.loc[val] 通过标签,选取DataFrame的单行数据
    df.loc[:,val] 通过标签,选取单列数据
    df.loc[,val1, val2] 通过标签,同时选取行和列对应的数据
    df.iloc[where] 通过整数位置,选取单个行数据
    df.oloc[:, where] 通过整数位置,选取单个列数据
    df.iloc[where_i, where_j] 通过整数位置,同时选取行和列对应的数据
    df.at[label_i, label_j] 通过行标签和列标签,选取对应的数据
    df.iat[i,j] 通过行和列的位置(整数),选取对应的数据
    reindex 通过标签选取行或列
    get_value,set_value 通过行和列标签选取数据

    算术运算和数据对齐

    pandas最重要的一个功能是:对不同索引的对象进行算术运算,当数据相加时,如果存在不同索引,则结果的索引是所有数据索引的并集。

    s1 = pd.Series([2,5,7,1], index=['a', 'c', 'd', 'e'])
    s2 = pd.Series([1,7,9,3,4], index=['a', 'c', 'e', 'f', 'g'])
    s1
    a    2
    c    5
    d    7
    e    1
    dtype: int64
    s2
    a    1
    c    7
    e    9
    f    3
    g    4
    dtype: int64
    #自动的数据对齐操作在不重叠的索引处引入了NA值,对于DataFrame会同时发生在行和列上
    s1 + s2
    a     3.0
    c    12.0
    d     NaN
    e    10.0
    f     NaN
    g     NaN
    dtype: float64
    

    在算术方法中填充值

    在对不同索引的对象进行算术运算时,我们可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0)。此时可以使用算术方法在fill_value传入参数0.

    df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),
                      columns=list('abcd'))
    df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),
                      columns=list('abcde'))
    df1
        a   b   c   d
    0   0.0 1.0 2.0 3.0
    1   4.0 5.0 6.0 7.0
    2   8.0 9.0 10.011.0
    df2
        a   b   c   d   e
    0   0.0 1.0 2.0 3.0 4.0
    1   5.0 6.0 7.0 8.0 9.0
    2   10.011.012.013.014.0
    3   15.016.017.018.019.0
    df1 + df2
        a   b   c   d   e
    0   0.0 2.0 4.0 6.0 NaN
    1   9.0 11.013.015.0NaN
    2   18.020.022.024.0NaN
    3   NaN NaN NaN NaN NaN
    #填充值0
    df1.add(df2,fill_value=0)
        a       b       c       d       e
    0   0.0     2.0     4.0     6.0     4.0
    1   9.0     11.0    13.0    15.0    9.0
    2   18.0    20.0    22.0    24.0    14.0
    3   15.0    16.0    17.0    18.0    19.0
    

    Series和DataFrame算术方法

    每个算术方法都有一个副本,以字母r开头,它会翻转参数。两个语句等价。

    方法 说明
    add +加
    sub, rsub -减
    div, rdiv /除
    floordiv, rfloordiv //底除
    mul, rmul *乘
    pow, rpow **指数

    DataFrame和Series之间的运算

    arr = np.arange(12).reshape((3,4))
    arr
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    arr[0]
    array([0, 1, 2, 3])
    #从arr减去arr[0],每一行都会执行这个操作。这叫做广播(broadcasting)
    arr - arr[0]
    array([[0, 0, 0, 0],
           [4, 4, 4, 4],
           [8, 8, 8, 8]])
    #DataFrame和Series之间的运算差不多也是如此
    frame3 = pd.DataFrame(np.arange(12).reshape((4,3)),
                         columns=list('abc'),
                         index=list('EMNF'))
    frame3
        a   b   c
    E   0   1   2
    M   3   4   5
    N   6   7   8
    F   9   10  11
    s3 = frame3.iloc[0]
    s3
    a    0
    b    1
    c    2
    Name: E, dtype: int64
    frame3 - s3
        a   b   c
    E   0   0   0
    M   3   3   3
    N   6   6   6
    F   9   9   9
    

    如果希望在列上传播,则必须使用算术运算方法。

    s4 = frame3['a']
    s4
    E    0
    M    3
    N    6
    F    9
    Name: a, dtype: int64
    frame3.sub(s4,axis='index')
        a   b   c
    E   0   1   2
    M   0   1   2
    N   0   1   2
    F   0   1   2
    

    函数应用和映射

    Numpy的函数也可以用于操作pandas对象:

    np.add(frame3,2)
        a   b   c
    E   2   3   4
    M   5   6   7
    N   8   9   10
    F   11  12  13
    

    另一个常见的操作是,将函数应用到各列或各行所形成的一维数组上。DataFrame的applay方法即可实现此功能。

    frame3
        a   b   c
    E   0   1   2
    M   3   4   5
    N   6   7   8
    F   9   10  11
    f = lambda x: x.max() - x.min()
    frame3.apply(f)
    a    9
    b    9
    c    9
    dtype: int64
    
    def f(x):
        return pd.Series([x.min(), x.max()], index=['min', 'max'])
    frame3.apply(f, axis='columns')
        min max
    E   0   2
    M   3   5
    N   6   8
    F   9   11
    
    frame4 = pd.DataFrame(np.random.randn(4,3),
                         columns=list('abc'),
                         index=list('DEFG'))
    frame4
        a           b           c
    D   0.279946    0.697885    -0.159838
    E   -0.890032   0.480782    1.053987
    F   -0.734350   -0.869877   0.439226
    G   1.591106    0.822776    0.350413
    #使用applymap函数得到frame4中各个浮点值的格式化字符串
    f = lambda x: '%.2f' %x
    frame4.applymap(f)
        a       b       c
    D   0.28    0.70    -0.16
    E   -0.89   0.48    1.05
    F   -0.73   -0.87   0.44
    G   1.59    0.82    0.35
    

    结语:有关pandas的入门介绍就写到此,上面的笔记都是自己看《利用Python进行数据分析》第五章节的记录,绝大部分是书中的例题,也有一小部分是自己的添加的。

    参考书籍:《利用Python进行数据分析》

    2019-06-13

    相关文章

      网友评论

          本文标题:pandas入门

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