美文网首页
Python 学习笔记之—— Pandas 库

Python 学习笔记之—— Pandas 库

作者: seniusen | 来源:发表于2019-12-09 11:05 被阅读0次
    import numpy as np
    import pandas as pd
    

    1. 基本的数据结构

    1.1 Series

    Series 是一维的标记数组,可以容纳任意数据类型,比如整数、字符串、浮点数或者 Python 对象,轴标记则称之为索引(index),其可以通过 s = pd.Series(data, index=index) 来简单地进行创建。

    这里,data 可以是一个字典、Numpy 数组或者是一个标量,传进去的 index 是一个轴标记的列表。

    # 通过数组来创建
    data = np.random.rand(5)
    s = pd.Series(data)
    print(s)
    index = ['a', 'b', 'c', 'd', 'e']
    s = pd.Series(data, index=index)
    print(s)
    index = ['a', 'a', 'c', 'd', 'e']
    pd.Series(data, index=index)
    
    0    0.161391
    1    0.399114
    2    0.239517
    3    0.174435
    4    0.509980
    dtype: float64
    
    a    0.161391
    b    0.399114
    c    0.239517
    d    0.174435
    e    0.509980
    dtype: float64
    
    a    0.161391
    a    0.399114
    c    0.239517
    d    0.174435
    e    0.509980
    dtype: float64
    

    如果不指定 index,则索引默认为 [0, 1...n-1]。而且索引并不一定必须是唯一的,只不过当进行一个不支持重复索引的操作时,会抛出一个异常。

    # 通过字典来创建
    d = {'b': 1, 'a': 0, 'c': 2}
    pd.Series(d)
    pd.Series(d, index=['a', 'b', 'c', 'd'])
    
    a    0.0
    b    1.0
    c    2.0
    d    NaN
    dtype: float64
    

    如果不指定 index,则索引默认为字典的键,如果指定了的话,我们就从字典中取出索引对应的数据,缺失的值则默认标记为 NaN

    # 通过标量来创建
    index = ['a', 'b', 'c', 'd', 'e']
    pd.Series(5, index)
    
    a    5
    b    5
    c    5
    d    5
    e    5
    dtype: int64
    

    如果通过标量来创建,那么必须指定 index,数值会重复来匹配索引的长度。

    print(s[0])
    print(s[1:-1])
    print(s[s > 0.40])
    s.dtype
    
    0.1613914172020462
    
    b    0.399114
    c    0.239517
    d    0.174435
    dtype: float64
    
    e    0.50998
    dtype: float64
    
    dtype('float64')
    

    Series 是类数组的,支持一些数组的操作,比如你可以通过切片来访问,也可以查看它的数据类型等。

    print(s['a'])
    s['e'] = 12
    print(s)
    'e' in s
    
    0.1613914172020462
    
    a     0.161391
    b     0.399114
    c     0.239517
    d     0.174435
    e    12.000000
    dtype: float64
    
    True
    

    Series 是类字典的,你可以通过索引得到它对应的值,也可以改变数据等。

    print(s * 2)
    print(np.exp(s))
    s[1:] + s[:-1]
    
    a     0.322783
    b     0.798228
    c     0.479035
    d     0.348871
    e    24.000000
    dtype: float64
    
    a         1.175145
    b         1.490504
    c         1.270636
    d         1.190574
    e    162754.791419
    dtype: float64
    
    a         NaN
    b    0.798228
    c    0.479035
    d    0.348871
    e         NaN
    dtype: float64
    

    Series 可以像数组一样支持向量化的操作,只不过这里它们会根据索引自动对齐,而不用我们去考虑,在其中一个 Series 中缺失的值会标记为 NaN

    s = pd.Series(np.random.randn(5), name='something')
    print(s)
    s = s.rename('another thing')
    s.name
    
    0    2.088204
    1   -0.251980
    2    0.191687
    3   -0.702280
    4    2.679027
    Name: something, dtype: float64
    
    
    'another thing'
    

    Series 还可以有一个名称的属性,我们也可以随时对其进行更改。

    1.2 DataFrame

    DataFrame 是二维标记的数据结构,它的列可以是不同的类型,可以将它看作是一个电子表格、SQL 表或者是包含 Series 对象的字典。DataFrame 接受很多种不同的输入:包含一维数组、列表、字典或者 Series 的字典;二维数组;另一个 DataFrame 等。同时,也可以选择性地传递索引(index)——行标记和列(columns)——列标记参数。

    # 从包含 Series 的字典创建
    d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
         'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
    df = pd.DataFrame(d)
    print(df)
    df1 = pd.DataFrame(d, index=['d', 'b', 'a'])
    print(df1)
    df2 = pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
    print(df2)
    
       one  two
    a  1.0  1.0
    b  2.0  2.0
    c  3.0  3.0
    d  NaN  4.0
    
       one  two
    d  NaN  4.0
    b  2.0  2.0
    a  1.0  1.0
    
       two three
    d  4.0   NaN
    b  2.0   NaN
    a  1.0   NaN
    

    结果中的索引将会是不同 Series 的并集,同时我们也可以分别指定索引和列。

    # 从数组或者列表创建
    d = {'one': [1., 2., 3., 4.],
         'two': [4., 3., 2., 1.]}
    print(pd.DataFrame(d))
    print(pd.DataFrame(d, index=['a', 'b', 'c', 'd']))
    
       one  two
    0  1.0  4.0
    1  2.0  3.0
    2  3.0  2.0
    3  4.0  1.0
    
       one  two
    a  1.0  4.0
    b  2.0  3.0
    c  3.0  2.0
    d  4.0  1.0
    

    这时候数组的大小必须相同,如果传递了索引的话,那么索引的长度必须和数组大小一致。

    print(df['one'])
    df['three'] = df['one'] * df['two']
    df['flag'] = df['one'] > 2
    print(df)
    del df['two']
    three = df.pop('three')
    print(df)
    df['foo'] = 'bar'
    df['one_trunc'] = df['one'][:2]
    print(df)
    
    a    1.0
    b    2.0
    c    3.0
    d    NaN
    Name: one, dtype: float64
    
       one  two  three   flag
    a  1.0  1.0    1.0  False
    b  2.0  2.0    4.0  False
    c  3.0  3.0    9.0   True
    d  NaN  4.0    NaN  False
    
       one   flag
    a  1.0  False
    b  2.0  False
    c  3.0   True
    d  NaN  False
    
       one   flag  foo  one_trunc
    a  1.0  False  bar        1.0
    b  2.0  False  bar        2.0
    c  3.0   True  bar        NaN
    d  NaN  False  bar        NaN
    

    我们可以把 DataFrame 看作是一个字典来对它的列执行取出、设置和删除操作。当插入一个标量的时候,这个值会填满整列。

    2. 10 分钟入门

    2.1 查看数据

    dates = pd.date_range('20130101', periods=6)
    df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
    print(df)
    
                       A         B         C         D
    2013-01-01 -0.894992  1.827753 -0.525777  0.187190
    2013-01-02 -0.844346  1.267231 -0.645592  0.919141
    2013-01-03  0.796179 -1.399534  0.686902  1.388934
    2013-01-04 -0.579014 -0.409705 -0.386375  1.032558
    2013-01-05 -1.676227  1.101409 -1.348775 -0.177341
    2013-01-06  0.024847 -0.205337  1.801102  0.265285
    
    print(df.head())
    print(df.tail(3))
    
       one  two
    a  1.0  1.0
    b  2.0  2.0
    c  3.0  3.0
    d  NaN  4.0
    
       one  two
    b  2.0  2.0
    c  3.0  3.0
    d  NaN  4.0
    
    print(df.index)
    df.columns
    
    DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
                   '2013-01-05', '2013-01-06'],
                  dtype='datetime64[ns]', freq='D')
    
    Index(['A', 'B', 'C', 'D'], dtype='object')
    
    # 快速显示数据的统计特性
    print(df.describe())
    
           one       two
    count  3.0  4.000000
    mean   2.0  2.500000
    std    1.0  1.290994
    min    1.0  1.000000
    25%    1.5  1.750000
    50%    2.0  2.500000
    75%    2.5  3.250000
    max    3.0  4.000000
    
    # 对列索引降序排列
    df = df.sort_index(axis=1, ascending=False)
    print(df)
    
       two  one
    a  1.0  1.0
    b  2.0  2.0
    c  3.0  3.0
    d  4.0  NaN
    
    # 对 B 列的数值排序
    df = df.sort_values(by='B')
    print(df)
    
                       A         B         C         D
    2013-01-03  0.796179 -1.399534  0.686902  1.388934
    2013-01-04 -0.579014 -0.409705 -0.386375  1.032558
    2013-01-06  0.024847 -0.205337  1.801102  0.265285
    2013-01-05 -1.676227  1.101409 -1.348775 -0.177341
    2013-01-02 -0.844346  1.267231 -0.645592  0.919141
    2013-01-01 -0.894992  1.827753 -0.525777  0.187190
    

    2.2 按照标记选择

    print(df.loc[dates[0:1]])
    
                       A         B         C        D
    2013-01-01 -0.894992  1.827753 -0.525777  0.18719
    
    print(df.loc['20130102':'20130104', ['A', 'B']])
    
                       A         B
    2013-01-03  0.796179 -1.399534
    2013-01-04 -0.579014 -0.409705
    2013-01-02 -0.844346  1.267231
    
    df.loc[dates[0], 'A']
    
    0.8144031024228705
    

    2.3 按照位置选择

    df.iloc[3]
    
    A    0.091327
    B   -0.570903
    C    1.855473
    D    1.807595
    Name: 2013-01-04 00:00:00, dtype: float64
    
    print(df.iloc[3:5, 0:2])
    
                       A         B
    2013-01-05 -1.676227  1.101409
    2013-01-02 -0.844346  1.267231
    
    print(df.iloc[1, 1])
    
    -0.4097050352704689
    

    2.4 布尔索引

    print(df[df.A > 0])
    
                       A         B         C         D
    2013-01-03  0.796179 -1.399534  0.686902  1.388934
    2013-01-06  0.024847 -0.205337  1.801102  0.265285
    
    print(df[df > 0])
    
                       A         B         C         D
    2013-01-03  0.796179       NaN  0.686902  1.388934
    2013-01-04       NaN       NaN       NaN  1.032558
    2013-01-06  0.024847       NaN  1.801102  0.265285
    2013-01-05       NaN  1.101409       NaN       NaN
    2013-01-02       NaN  1.267231       NaN  0.919141
    2013-01-01       NaN  1.827753       NaN  0.187190
    

    2.5 缺失数据

    df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
    df1.loc[dates[0]:dates[1], 'E'] = 1
    print(df1)
    
                       A         B         C         D    E
    2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
    2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
    2013-01-03  0.796179 -1.399534  0.686902  1.388934  NaN
    2013-01-04 -0.579014 -0.409705 -0.386375  1.032558  NaN
    
    print(df1.dropna(how='any')) # 删除任意包含 NaN 的行
    
                       A         B         C         D    E
    2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
    2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
    
    print(df1.fillna(value=5)) # 填充缺失数据
    
                       A         B         C         D    E
    2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
    2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
    2013-01-03  0.796179 -1.399534  0.686902  1.388934  5.0
    2013-01-04 -0.579014 -0.409705 -0.386375  1.032558  5.0
    
    print(pd.isna(df1))
    
                    A      B      C      D      E
    2013-01-01  False  False  False  False  False
    2013-01-02  False  False  False  False  False
    2013-01-03  False  False  False  False   True
    2013-01-04  False  False  False  False   True
    

    2.6 操作

    df.mean()
    
    A    0.493828
    B   -0.555683
    C    1.068909
    D   -0.675655
    dtype: float64
    
    df.mean(1)
    
    2013-01-01    0.725959
    2013-01-02    0.317094
    2013-01-03   -0.834986
    2013-01-04    0.795873
    2013-01-05   -0.076024
    2013-01-06   -0.430818
    Freq: D, dtype: float64
    
    df.apply(lambda x: x.max() - x.min())
    
    A    2.283890
    B    2.470330
    C    2.813372
    D    3.389214
    dtype: float64
    
    s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
    s.str.lower()
    
    0       a
    1       b
    2       c
    3    aaba
    4    baca
    5     NaN
    6    caba
    7     dog
    8     cat
    dtype: object
    
    df2 = pd.DataFrame({'one':['A', 'B'], 'two':['c', 'd']})
    print(df2)
    df2['one'] = df2['one'].apply(str.lower)
    df2['two'] = df2['two'].apply(str.upper)
    print(df2)
    
      one two
    0   A   c
    1   B   d
      one two
    0   a   C
    1   b   D
    

    2.7 合并

    df = pd.DataFrame(np.random.randn(5, 4))
    print(df)
    
              0         1         2         3
    0 -0.811113 -0.087698 -1.980786  0.129838
    1 -0.083298 -0.803188  0.012908 -1.052246
    2  0.534317  0.411549  1.638672 -0.182032
    3  0.002322  0.857579  1.716546 -0.531305
    4  0.210017  0.156584 -0.487976 -1.230442
    
    pieces = [df[:2], df[2:4], df[4:]]
    print(pd.concat(pieces))
    
              0         1         2         3
    0 -0.811113 -0.087698 -1.980786  0.129838
    1 -0.083298 -0.803188  0.012908 -1.052246
    2  0.534317  0.411549  1.638672 -0.182032
    3  0.002322  0.857579  1.716546 -0.531305
    4  0.210017  0.156584 -0.487976 -1.230442
    
    left = pd.DataFrame({'key': ['val', 'foo', 'bar'], 'lval': [0, 1, 2]})
    right = pd.DataFrame({'key': ['foo', 'foo', 'bar', 'end'], 'rval': [4, 3, 5, 6]})
    print(left)
    print(right)
    
       key  lval
    0  val     0
    1  foo     1
    2  bar     2
    
       key  rval
    0  foo     4
    1  foo     3
    2  bar     5
    3  end     6
    
    print(pd.merge(left, right, on='key')) # 基于 key 这一列合并
    
       key  lval  rval
    0  foo     1     4
    1  foo     1     3
    2  bar     2     5
    
    print(pd.merge(left, right, how='inner')) # 内连接也就是基于键的交集
    
       key  lval  rval
    0  foo     1     4
    1  foo     1     3
    2  bar     2     5
    
    print(pd.merge(left, right, how='left')) # 左连接以第一个 DataFrame 为主
    
       key  lval  rval
    0  val     0   NaN
    1  foo     1   4.0
    2  foo     1   3.0
    3  bar     2   5.0
    
    print(pd.merge(left, right, how='right')) # 右连接以第二个 DataFrame 为主
    
       key  lval  rval
    0  foo   1.0     4
    1  foo   1.0     3
    2  bar   2.0     5
    3  end   NaN     6
    
    print(pd.merge(left, right, how='outer')) # 外连接也就是基于键的并集
    
       key  lval  rval
    0  val   0.0   NaN
    1  foo   1.0   4.0
    2  foo   1.0   3.0
    3  bar   2.0   5.0
    4  end   NaN   6.0
    

    3. 一个小例子

    name = ['张飞', '关羽', '黄忠', '赵云', '典韦', '典韦']
    chinese = [66, 95, 95, 90, 80, 80]
    english = [65, 85, 92, 88, 90, 90]
    math = [np.nan, 98, 96, 77, 90, 90]
    dic = dict({'语文':chinese, '英语':english, '数学':math})
    score = pd.DataFrame(dic, index=name)
    print(score)
    
          数学  英语  语文
    张飞   NaN  65  66
    关羽  98.0  85  95
    黄忠  96.0  92  95
    赵云  77.0  88  90
    典韦  90.0  90  80
    典韦  90.0  90  80
    
    score = score.drop_duplicates()
    
    score = score.fillna(score['数学'].mean())
    print(score)
    
          数学  英语  语文
    张飞  90.2  65  66
    关羽  98.0  85  95
    黄忠  96.0  92  95
    赵云  77.0  88  90
    典韦  90.0  90  80
    
    def cal_total(df):
        df['总分'] = df['英语'] + df['英语'] + df['英语']
        return df
    
    #print(cal_total(score))
    score = score.apply(cal_total, axis=1)
    print(score)
    
          数学    英语    语文     总分
    张飞  90.2  65.0  66.0  195.0
    关羽  98.0  85.0  95.0  255.0
    黄忠  96.0  92.0  95.0  276.0
    赵云  77.0  88.0  90.0  264.0
    典韦  90.0  90.0  80.0  270.0
    
    score = score.sort_values(by='总分')
    print(score)
    
          数学    英语    语文     总分
    张飞  90.2  65.0  66.0  195.0
    关羽  98.0  85.0  95.0  255.0
    赵云  77.0  88.0  90.0  264.0
    典韦  90.0  90.0  80.0  270.0
    黄忠  96.0  92.0  95.0  276.0
    

    相关文章

      网友评论

          本文标题:Python 学习笔记之—— Pandas 库

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