美文网首页VBA
笔记:Python之Pandas的使用技巧

笔记:Python之Pandas的使用技巧

作者: 南有妖尾 | 来源:发表于2019-11-17 12:20 被阅读0次

    Pandas的使用技巧相关知识点总结

    pandas的使用技巧相关知识点总结表.png

    一、数学计算与统计基础

    (1)基本参数axis和skipna

    # 基本参数:axis、skipna
    # 创建dataframe
    df = pd.DataFrame({'key1':[4,5,3,np.nan,2],
                     'key2':[1,2,np.nan,4,5],
                     'key3':[1,2,3,'j','k']},
                     index = ['a','b','c','d','e'])
    print(df)
    print(df['key1'],df['key1'].dtype)
    print(df['key2'],df['key2'].dtype)
    print(df['key3'],df['key3'].dtype)
    print('---------------------')
    
    
    data = df.mean() 
    print(data)
    # .mean()计算均值,只统计元素是数字的列
    # 按列计算每列的平均值,因key3含有字符串,返回只有key1和key2
    
    # 单独统计一列,就索引要统计那列即可
    # 单独统计key2这列
    data2 = df['key2'].mean()
    print(data2)
    print('---------------------')
    
    # 参数axis,默认为0,按列来计算
    # 参数axis=1,则按行来计算
    data3 = df.mean(axis=1)
    print(data3)
    print('---------------------')
    
    
    # 从返回的data3结果来看,因原数据dataframe中含Nan,默认自动忽略Nan
    # 参数skipna就是定义是否忽略Nan
    # 参数skipna默认为True → 忽略Nan
    # 参数skipna为False → 不忽略Nan,有Nan的列统计结果仍为Nan
    data4 = df.mean(skipna=False)
    data5 = df.mean(axis=1,skipna=False)
    print(data4)
    print(data5)
    

    输出结果:

       key1  key2 key3
    a   4.0   1.0    1
    b   5.0   2.0    2
    c   3.0   NaN    3
    d   NaN   4.0    j
    e   2.0   5.0    k
    a    4.0
    b    5.0
    c    3.0
    d    NaN
    e    2.0
    Name: key1, dtype: float64 float64
    a    1.0
    b    2.0
    c    NaN
    d    4.0
    e    5.0
    Name: key2, dtype: float64 float64
    a    1
    b    2
    c    3
    d    j
    e    k
    Name: key3, dtype: object object
    ---------------------
    key1    3.5
    key2    3.0
    dtype: float64
    3.0
    ---------------------
    a    2.5
    b    3.5
    c    3.0
    d    4.0
    e    3.5
    dtype: float64
    ---------------------
    key1   NaN
    key2   NaN
    dtype: float64
    a    2.5
    b    3.5
    c    NaN
    d    NaN
    e    3.5
    dtype: float64
    

    (2)主要数学计算方法

    --->>> 数学计算方法①

    # 主要数学计算方法①
    # 可用于Series和DataFrame
    
    df = pd.DataFrame({'key1':np.arange(10),
                      'key2':np.random.rand(10)*10})
    print(df)
    print('-----------------')
    
    print(df.count(),'→ count统计非Na值的数量\n')
    print(df.min(),'→ min统计最小值\n',df['key2'].max(),'→ max统计最大值\n')
    print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置\n')
    print(df.sum(),'→ sum求和\n')
    print(df.mean(),'→ mean求平均值\n')
    print(df.median(),'→ median求算数中位数,50%分位数\n')
    print(df.std(),'\n',df.var(),'→ std,var分别求标准差,方差\n')
    print(df.skew(),'→ skew样本的偏度\n')
    print(df.kurt(),'→ kurt样本的峰度\n')
    

    输出结果:

       key1      key2
    0     0  4.253328
    1     1  0.960379
    2     2  3.511730
    3     3  2.509393
    4     4  0.054089
    5     5  8.111823
    6     6  4.844677
    7     7  3.198498
    8     8  3.034000
    9     9  3.702352
    -----------------
    key1    10
    key2    10
    dtype: int64 → count统计非Na值的数量
    
    key1    0.000000
    key2    0.054089
    dtype: float64 → min统计最小值
     8.111822673021239 → max统计最大值
    
    key1    6.750000
    key2    4.115584
    Name: 0.75, dtype: float64 → quantile统计分位数,参数q确定位置
    
    key1    45.000000
    key2    34.180269
    dtype: float64 → sum求和
    
    key1    4.500000
    key2    3.418027
    dtype: float64 → mean求平均值
    
    key1    4.500000
    key2    3.355114
    dtype: float64 → median求算数中位数,50%分位数
    
    key1    3.027650
    key2    2.191696
    dtype: float64 
     key1    9.166667
    key2    4.803533
    dtype: float64 → std,var分别求标准差,方差
    
    key1    0.000000
    key2    0.701767
    dtype: float64 → skew样本的偏度
    
    key1   -1.200000
    key2    1.858886
    dtype: float64 → kurt样本的峰度
    

    --->>> 数学计算方法②

    # 主要数学计算方法②
    # 可用于Series和DataFrame(2)
    df = pd.DataFrame({'key1':np.arange(10),
                      'key2':np.random.rand(10)*10})
    print(df)
    print('-----------------')
    
    # .cumsum()计算累计和
    df['key1_s'] = df['key1'].cumsum()
    df['key2_s'] = df['key2'].cumsum()
    print(df,'→ cumsum样本的累计和\n')
    print('-----------------')
    
    # .cumprod()计算累计积
    df['key1_p'] = df['key1'].cumprod()
    df['key2_p'] = df['key2'].cumprod()
    print(df,'→ cumprod样本的累计积\n')
    print('-----------------')
    
    # .cummax()求累计最大值,就是指累计的过程中要累计的数据中最大的值,就会一直被填充
    # .cummin()求累计最小值,就是指累计的过程中要列举的数据中最小的值,就会一直被填充
    print(df.cummax(),'\n',df.cummin(),'→ cummax,cummin分别求累计最大值,累计最小值\n')
    # 会填充key1,和key2的值
    

    输出结果:

       key1      key2
    0     0  6.782298
    1     1  8.826684
    2     2  5.330644
    3     3  1.284093
    4     4  2.040580
    5     5  5.194812
    6     6  4.981178
    7     7  3.467392
    8     8  6.802496
    9     9  1.212725
    -----------------
       key1      key2  key1_s     key2_s
    0     0  6.782298       0   6.782298
    1     1  8.826684       1  15.608982
    2     2  5.330644       3  20.939626
    3     3  1.284093       6  22.223719
    4     4  2.040580      10  24.264299
    5     5  5.194812      15  29.459111
    6     6  4.981178      21  34.440289
    7     7  3.467392      28  37.907680
    8     8  6.802496      36  44.710176
    9     9  1.212725      45  45.922902 → cumsum样本的累计和
    
    -----------------
       key1      key2  key1_s     key2_s  key1_p         key2_p
    0     0  6.782298       0   6.782298       0       6.782298
    1     1  8.826684       1  15.608982       0      59.865201
    2     2  5.330644       3  20.939626       0     319.120053
    3     3  1.284093       6  22.223719       0     409.779981
    4     4  2.040580      10  24.264299       0     836.188665
    5     5  5.194812      15  29.459111       0    4343.843239
    6     6  4.981178      21  34.440289       0   21637.455452
    7     7  3.467392      28  37.907680       0   75025.529833
    8     8  6.802496      36  44.710176       0  510360.865310
    9     9  1.212725      45  45.922902       0  618927.582201 → cumprod样本的累计积
    
    -----------------
       key1      key2  key1_s     key2_s  key1_p         key2_p
    0   0.0  6.782298     0.0   6.782298     0.0       6.782298
    1   1.0  8.826684     1.0  15.608982     0.0      59.865201
    2   2.0  8.826684     3.0  20.939626     0.0     319.120053
    3   3.0  8.826684     6.0  22.223719     0.0     409.779981
    4   4.0  8.826684    10.0  24.264299     0.0     836.188665
    5   5.0  8.826684    15.0  29.459111     0.0    4343.843239
    6   6.0  8.826684    21.0  34.440289     0.0   21637.455452
    7   7.0  8.826684    28.0  37.907680     0.0   75025.529833
    8   8.0  8.826684    36.0  44.710176     0.0  510360.865310
    9   9.0  8.826684    45.0  45.922902     0.0  618927.582201 
        key1      key2  key1_s    key2_s  key1_p    key2_p
    0   0.0  6.782298     0.0  6.782298     0.0  6.782298
    1   0.0  6.782298     0.0  6.782298     0.0  6.782298
    2   0.0  5.330644     0.0  6.782298     0.0  6.782298
    3   0.0  1.284093     0.0  6.782298     0.0  6.782298
    4   0.0  1.284093     0.0  6.782298     0.0  6.782298
    5   0.0  1.284093     0.0  6.782298     0.0  6.782298
    6   0.0  1.284093     0.0  6.782298     0.0  6.782298
    7   0.0  1.284093     0.0  6.782298     0.0  6.782298
    8   0.0  1.284093     0.0  6.782298     0.0  6.782298
    9   0.0  1.212725     0.0  6.782298     0.0  6.782298 → cummax,cummin分别求累计最大值,累计最小
    

    (3)唯一值判断.unique()

    # 唯一值:.unique()
    
    # 创建Series
    s = pd.Series(list('asdvasdcfgg'))
    print(s)
    print('---------------')
    
    # sq是只有为唯一值的Seires
    sq = s.unique()
    print(sq,type(sq))
    
    # 将唯一值转变为Series
    # 得到一个唯一值数组
    # 通过pd.Series重新变成新的Series
    s2 = pd.Series(sq)
    print(s2)
    
    sq.sort()
    print(sq)
    # 重新排序
    

    输出结果:

    0     a
    1     s
    2     d
    3     v
    4     a
    5     s
    6     d
    7     c
    8     f
    9     g
    10    g
    dtype: object
    ---------------
    ['a' 's' 'd' 'v' 'c' 'f' 'g'] <class 'numpy.ndarray'>
    0    a
    1    s
    2    d
    3    v
    4    c
    5    f
    6    g
    dtype: object
    ['a' 'c' 'd' 'f' 'g' 's' 'v']
    

    (4)值values的计数.value_counts()

    # 值计数:.value_counts()
    
    s = pd.Series(list('asdvasdcfgg'))
    print(s)
    print('-----------------')
    
    # 对s的values进行计数(次数)
    sc = s.value_counts()
    print(sc)
    sc2 = s.value_counts(sort=False)
    print(sc2)
    # 得到一个新的Series,计算出不同值出现的频率
    # sort参数:排序,默认为True
    print('-----------------')
    print(s)
    

    输出结果:

    0     a
    1     s
    2     d
    3     v
    4     a
    5     s
    6     d
    7     c
    8     f
    9     g
    10    g
    dtype: object
    -----------------
    a    2
    s    2
    g    2
    d    2
    f    1
    c    1
    v    1
    dtype: int64
    v    1
    d    2
    g    2
    c    1
    f    1
    s    2
    a    2
    dtype: int64
    -----------------
    0     a
    1     s
    2     d
    3     v
    4     a
    5     s
    6     d
    7     c
    8     f
    9     g
    10    g
    dtype: object
    

    (5)成员资格判断.isin()

    # 成员资格:.isin()
    
    s = pd.Series(np.arange(10,15))
    df = pd.DataFrame({'key1':list('asdcbvasd'),
                      'key2':np.arange(4,13)})
    print(s)
    print(df)
    print('-----')
    
    print(s.isin([5,14])) # 判断5或14是否在s里
    print(df.isin(['a','bc','10',8]))
    # 用[]表示
    # 得到一个布尔值的Series或者Dataframe
    

    输出结果:

    0    10
    1    11
    2    12
    3    13
    4    14
    dtype: int32
      key1  key2
    0    a     4
    1    s     5
    2    d     6
    3    c     7
    4    b     8
    5    v     9
    6    a    10
    7    s    11
    8    d    12
    -----
    0    False
    1    False
    2    False
    3    False
    4     True
    dtype: bool
        key1   key2
    0   True  False
    1  False  False
    2  False  False
    3  False  False
    4  False   True
    5  False  False
    6   True  False
    7  False  False
    8  False  False
    

    二、文本数据的常用操作

    Pandas针对字符串配备了一套方法,使其易于对数组的每个元素进行操作。

    (1)通过str访问文本数据

    # 通过str访问文本数据并且自动排除丢失/Nan值
    
    # 创建Series和Dataframe
    s = pd.Series(['A','b','C','bbhello','123',np.nan,'hj'])
    df = pd.DataFrame({'key1':list('abcdef'),
                      'key2':['hee','fv','w','hija','123',np.nan]})
    print(s)
    print('------')
    print(df)
    print('----------------')
    
    # 通过str访问Series和Dataframe类型的文本数据
    # str访问会自动过滤Nan值
    print(s.str.count('b')) # 对s里面的每次个数据的b元素进行计数
    print(df['key2'].str.upper()) # 将df里面的key2列的元素变为大写
    
    # 对columns用str访问,因为df.columns是一个Index对象,也可使用.str
    df.columns = df.columns.str.upper()
    print(df)
    

    输出结果:

    0          A
    1          b
    2          C
    3    bbhello
    4        123
    5        NaN
    6         hj
    dtype: object
    ------
      key1  key2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    ----------------
    0    0.0
    1    1.0
    2    0.0
    3    2.0
    4    0.0
    5    NaN
    6    0.0
    dtype: float64
    0     HEE
    1      FV
    2       W
    3    HIJA
    4     123
    5     NaN
    Name: key2, dtype: object
      KEY1  KEY2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    

    (2)字符串常用方法

    其实就是str不可变序列里面的针对字符串的方法,都可以通过str对pandas的文本数据进行操作。
    --->>>字符串常用方法①

    # 字符串常用方法①- lower,upper,len,startswith,endswith
    
    s = pd.Series(['A','b','bbhello','123',np.nan])
    print(s)
    print('----------------')
    
    # 将文本数据的字符串字母变小写
    print(s.str.lower(),'→ lower小写\n')
    # 将文本数据的字符串字母变大写
    print(s.str.upper(),'→ upper大写\n')
    # 计数每行数据的字符串长度
    print(s.str.len(),'→ len字符长度\n')
    print(s.str.startswith('b'),'→ 判断起始是否为a\n')
    print(s.str.endswith('3'),'→ 判断结束是否为3\n')
    

    输出结果:

    0          A
    1          b
    2    bbhello
    3        123
    4        NaN
    dtype: object
    ----------------
    0          a
    1          b
    2    bbhello
    3        123
    4        NaN
    dtype: object → lower小写
    
    0          A
    1          B
    2    BBHELLO
    3        123
    4        NaN
    dtype: object → upper大写
    
    0    1.0
    1    1.0
    2    7.0
    3    3.0
    4    NaN
    dtype: float64 → len字符长度
    
    0    False
    1     True
    2     True
    3    False
    4      NaN
    dtype: object → 判断起始是否为a
    
    0    False
    1    False
    2    False
    3     True
    4      NaN
    dtype: object → 判断结束是否为3
    

    --->>>字符串常用方法②

    # 字符串常用方法② - strip
    
    # 创建Series和Dataframe
    s = pd.Series([' jack', 'jill ', ' jesse ', 'frank'])
    df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
                      index=range(3))
    print(s)
    print(df)
    print('-------------')
    
    print(s.str.strip())  # 去除字符串中的空格
    print(s.str.lstrip())  # 去除字符串中的左空格
    print(s.str.rstrip())  # 去除字符串中的右空格
    
    #df.columns = df.columns.str.strip()
    #print(df)
    # 这里去掉了columns的前后空格,但没有去掉中间空格
    # 那就可以用replace将中间空格替换为其他
    

    输出结果:

    0       jack
    1      jill 
    2     jesse 
    3      frank
    dtype: object
        Column A    Column B 
    0   -0.680736    0.817757
    1   -1.037254   -1.264084
    2    0.424927   -1.150749
    -------------
    0     jack
    1     jill
    2    jesse
    3    frank
    dtype: object
    0      jack
    1     jill 
    2    jesse 
    3     frank
    dtype: object
    0      jack
    1      jill
    2     jesse
    3     frank
    dtype: object
    

    --->>>字符串常用方法③

    # 字符串常用方法(3) - replace
    
    df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
                      index=range(3))
    print(df)
    df.columns = df.columns.str.replace(' ','-')
    print(df)
    # 用.replace替换,将中间的空格用“-”替换
    
    df.columns = df.columns.str.replace('-','hehe',n=1) 
    print(df)
    # “-”用hehe来替换,且只替换一个“-”
    # 参数n=1,表示替换个数为1个
    

    输出结果:

        Column A    Column B 
    0    0.143967   -0.426351
    1   -1.210151    0.320342
    2   -0.825522   -1.299585
       -Column-A-  -Column-B-
    0    0.143967   -0.426351
    1   -1.210151    0.320342
    2   -0.825522   -1.299585
       heheColumn-A-  heheColumn-B-
    0       0.143967      -0.426351
    1      -1.210151       0.320342
    2      -0.825522      -1.299585
    

    --->>>字符串常用方法④【重点掌握知识!】

    # 字符串常用方法④ - split、rsplit
    
    s = pd.Series(['a,b,c','1,2,3',['a,,,c'],np.nan])
    print(s)
    print(s.str.split(',')) # 根据逗号进行拆分
    print('-----')
    # 类似字符串的split
    # 返回的数据里,因为split只用于字符串不用于列表,所以['a,,,c']返回Nan
    
    print(s.str.split(',')[0]) # 选取拆分后的第一行
    print('-----')
    # 直接索引得到一个list
    
    print(s.str.split(',').str[0]) # 选择第一个元素
    print(s.str.split(',').str.get(1)) # 选择第二个元素
    print('-----')
    # 可以使用get或[]符号访问拆分列表中的元素
    
    print(s.str.split(',', expand=True)) # 分割拓展全部
    print(s.str.split(',', expand=True, n = 1))
    print(s.str.rsplit(',', expand=True, n = 1))
    print('-----')
    # 参数expand可以轻松扩展此操作以返回DataFrame
    # expand参数,默认为False,expand=True可以分割拓展全部
    # n参数限制分割数,n=1,分割数为1,只分隔1列,其他列还是连在一起
    # rsplit类似于split,反向工作,即从字符串的末尾到字符串的开头
    
    # 对Dataframe进行split操作
    df = pd.DataFrame({'key1':['a,b,c','1,2,3',[':,., ']],
                     'key2':['a-b-c','1-2-3',[':-.- ']]})
    print(df)
    print(df['key2'].str.split('-'))
    # Dataframe使用split
    

    输出结果:

    0      a,b,c
    1      1,2,3
    2    [a,,,c]
    3        NaN
    dtype: object
    0    [a, b, c]
    1    [1, 2, 3]
    2          NaN
    3          NaN
    dtype: object
    -----
    ['a', 'b', 'c']
    -----
    0      a
    1      1
    2    NaN
    3    NaN
    dtype: object
    0      b
    1      2
    2    NaN
    3    NaN
    dtype: object
    -----
         0    1    2
    0    a    b    c
    1    1    2    3
    2  NaN  NaN  NaN
    3  NaN  NaN  NaN
         0    1
    0    a  b,c
    1    1  2,3
    2  NaN  NaN
    3  NaN  NaN
         0    1
    0  a,b    c
    1  1,2    3
    2  NaN  NaN
    3  NaN  NaN
    -----
          key1     key2
    0    a,b,c    a-b-c
    1    1,2,3    1-2-3
    2  [:,., ]  [:-.- ]
    0    [a, b, c]
    1    [1, 2, 3]
    2          NaN
    Name: key2, dtype: object
    

    (3)字符串索引

    # 字符串索引
    
    s = pd.Series(['A','b','C','bbhello','123',np.nan,'hj'])
    df = pd.DataFrame({'key1':list('abcdef'),
                      'key2':['hee','fv','w','hija','123',np.nan]})
    print(s)
    print(df)
    print('-----------------------------')
    
    print(s.str[0])  # 取第一个字符串
    print(s.str[:2])  # 取前两个字符串
    print(df['key2'].str[0]) 
    # str之后和字符串本身索引方式相同
    

    输出结果:

    0          A
    1          b
    2          C
    3    bbhello
    4        123
    5        NaN
    6         hj
    dtype: object
      key1  key2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    -----------------------------
    0      A
    1      b
    2      C
    3      b
    4      1
    5    NaN
    6      h
    dtype: object
    0      A
    1      b
    2      C
    3     bb
    4     12
    5    NaN
    6     hj
    dtype: object
    0      h
    1      f
    2      w
    3      h
    4      1
    5    NaN
    Name: key2, dtype: object
    

    三、pandas的合并merge、join

    Pandas具有全功能的,高性能内存中连接操作,与SQL等关系数据库非常相似。

    (1)合并merge

    pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=('_x', '_y'), copy=True, indicator=False)

    --->>> merge的基本使用:

    # merge合并 → 类似excel的vlookup
    
    df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                         'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3']})
    df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                          'C': ['C0', 'C1', 'C2', 'C3'],
                          'D': ['D0', 'D1', 'D2', 'D3']})
    df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                        'key2': ['K0', 'K1', 'K0', 'K1'],
                        'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3']})
    df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                        'key2': ['K0', 'K0', 'K0', 'K0'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
    print(df1)
    print(df2)
    print('---------------------------------')
    print(pd.merge(df1, df2, on='key')) 
    # 左边是df1;右边是df2,根据key作为参考键进行合并
    # on表示参考键
    print('---------------------------------')
    
    print(df3)
    print(df4)
    print('---------------------------------')
    print(pd.merge(df3, df4, on=['key1','key2']))
    # 多个链接键
    # 就是参考键有两个key1和key2都能匹配上的就合并表格
    

    输出结果:

        A   B key
    0  A0  B0  K0
    1  A1  B1  K1
    2  A2  B2  K2
    3  A3  B3  K3
        C   D key
    0  C0  D0  K0
    1  C1  D1  K1
    2  C2  D2  K2
    3  C3  D3  K3
    ---------------------------------
        A   B key   C   D
    0  A0  B0  K0  C0  D0
    1  A1  B1  K1  C1  D1
    2  A2  B2  K2  C2  D2
    3  A3  B3  K3  C3  D3
    ---------------------------------
        A   B key1 key2
    0  A0  B0   K0   K0
    1  A1  B1   K0   K1
    2  A2  B2   K1   K0
    3  A3  B3   K2   K1
        C   D key1 key2
    0  C0  D0   K0   K0
    1  C1  D1   K1   K0
    2  C2  D2   K1   K0
    3  C3  D3   K2   K0
    ---------------------------------
        A   B key1 key2   C   D
    0  A0  B0   K0   K0  C0  D0
    1  A2  B2   K1   K0  C1  D1
    2  A2  B2   K1   K0  C2  D2
    

    --->>> merge的参数how,表示合并的方式:

    # 参数how → 合并方式
    df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                        'key2': ['K0', 'K1', 'K0', 'K1'],
                        'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3']})
    df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                        'key2': ['K0', 'K0', 'K0', 'K0'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
    print(df3)
    print(df4)
    print('---------------------------------')
    print(pd.merge(df3, df4,on=['key1','key2'], how = 'inner'))  
    print('------')
    # how默认为inner → 取交集
    
    print(pd.merge(df3, df4, on=['key1','key2'], how = 'outer'))  
    print('------')
    # how=outer → 取并集,数据缺失范围NaN
    
    print(pd.merge(df3, df4, on=['key1','key2'], how = 'left'))  
    print('------')
    # how=left → 按照df3为参考合并,数据缺失范围NaN
    # 以df3为主,保留df3有的,将df4合并到df3中
    
    print(pd.merge(df3, df4, on=['key1','key2'], how = 'right'))  
    # how=right → 按照df4为参考合并,数据缺失范围NaN
    # 以df4为主,保留df4有的,将df3合并到df4中
    

    输出结果:

        A   B key1 key2
    0  A0  B0   K0   K0
    1  A1  B1   K0   K1
    2  A2  B2   K1   K0
    3  A3  B3   K2   K1
        C   D key1 key2
    0  C0  D0   K0   K0
    1  C1  D1   K1   K0
    2  C2  D2   K1   K0
    3  C3  D3   K2   K0
    ---------------------------------
        A   B key1 key2   C   D
    0  A0  B0   K0   K0  C0  D0
    1  A2  B2   K1   K0  C1  D1
    2  A2  B2   K1   K0  C2  D2
    ------
         A    B key1 key2    C    D
    0   A0   B0   K0   K0   C0   D0
    1   A1   B1   K0   K1  NaN  NaN
    2   A2   B2   K1   K0   C1   D1
    3   A2   B2   K1   K0   C2   D2
    4   A3   B3   K2   K1  NaN  NaN
    5  NaN  NaN   K2   K0   C3   D3
    ------
        A   B key1 key2    C    D
    0  A0  B0   K0   K0   C0   D0
    1  A1  B1   K0   K1  NaN  NaN
    2  A2  B2   K1   K0   C1   D1
    3  A2  B2   K1   K0   C2   D2
    4  A3  B3   K2   K1  NaN  NaN
    ------
         A    B key1 key2   C   D
    0   A0   B0   K0   K0  C0  D0
    1   A2   B2   K1   K0  C1  D1
    2   A2   B2   K1   K0  C2  D2
    3  NaN  NaN   K2   K0  C3  D3
    

    --->>> merge的参数 left_on, right_on, left_index, right_index:

    # 参数 left_on, right_on, left_index, right_index → 当键不为一个列时,可以单独设置左键与右键
    df1 = pd.DataFrame({'lkey':list('bbacaab'),
                       'data1':range(7)})
    df2 = pd.DataFrame({'rkey':list('abd'),
                       'date2':range(3)})
    print(pd.merge(df1, df2, left_on='lkey', right_on='rkey'))
    print('------')
    # df1以‘lkey’为键,df2以‘rkey’为键
    
    df1 = pd.DataFrame({'key':list('abcdfeg'),
                       'data1':range(7)})
    df2 = pd.DataFrame({'date2':range(100,105)},
                      index = list('abcde'))
    print(pd.merge(df1, df2, left_on='key', right_index=True))
    # df1以‘key’为键,df2以index为键
    # left_index:为True时,第一个df以index为键,默认False
    # right_index:为True时,第二个df以index为键,默认False
    
    # 所以left_on, right_on, left_index, right_index可以相互组合:
    # left_on + right_on, left_on + right_index, left_index + right_on, left_index + right_index
    

    输出结果:

       data1 lkey  date2 rkey
    0      0    b      1    b
    1      1    b      1    b
    2      6    b      1    b
    3      2    a      0    a
    4      4    a      0    a
    5      5    a      0    a
    ------
       data1 key  date2
    0      0   a    100
    1      1   b    101
    2      2   c    102
    3      3   d    103
    5      5   e    104
    

    --->>> merge的参数sort,排序

    # 参数 sort
    
    df1 = pd.DataFrame({'key':list('bbacaab'),
                       'data1':[1,3,2,4,5,9,7]})
    df2 = pd.DataFrame({'key':list('abd'),
                       'date2':[11,2,33]})
    print(df1)
    print(df2)
    x1 = pd.merge(df1,df2, on = 'key', how = 'outer') 
    x2 = pd.merge(df1,df2, on = 'key', sort=True, how = 'outer')
    print(x1)
    print(x2)
    print('------')
    # sort:按照字典顺序通过 连接键 对结果DataFrame进行排序。默认为False,设置为False会大幅提高性能
    
    print(x2.sort_values('data1')) # 对data1进行排序
    # 也可直接用Dataframe的排序方法:sort_values,sort_index
    

    输出结果:

       data1 key
    0      1   b
    1      3   b
    2      2   a
    3      4   c
    4      5   a
    5      9   a
    6      7   b
       date2 key
    0     11   a
    1      2   b
    2     33   d
       data1 key  date2
    0    1.0   b    2.0
    1    3.0   b    2.0
    2    7.0   b    2.0
    3    2.0   a   11.0
    4    5.0   a   11.0
    5    9.0   a   11.0
    6    4.0   c    NaN
    7    NaN   d   33.0
       data1 key  date2
    0    2.0   a   11.0
    1    5.0   a   11.0
    2    9.0   a   11.0
    3    1.0   b    2.0
    4    3.0   b    2.0
    5    7.0   b    2.0
    6    4.0   c    NaN
    7    NaN   d   33.0
    ------
       data1 key  date2
    3    1.0   b    2.0
    0    2.0   a   11.0
    4    3.0   b    2.0
    6    4.0   c    NaN
    1    5.0   a   11.0
    5    7.0   b    2.0
    2    9.0   a   11.0
    7    NaN   d   33.0
    

    (2)join链接

    # pd.join() → 直接通过索引链接
    
    left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                         'B': ['B0', 'B1', 'B2']},
                        index=['K0', 'K1', 'K2'])
    right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
                          'D': ['D0', 'D2', 'D3']},
                         index=['K0', 'K2', 'K3'])
    print(left)
    print(right)
    print(left.join(right))
    print(left.join(right, how='outer'))  
    print('-----')
    # 等价于:pd.merge(left, right, left_index=True, right_index=True, how='outer')
    
    df1 = pd.DataFrame({'key':list('bbacaab'),
                       'data1':[1,3,2,4,5,9,7]})
    df2 = pd.DataFrame({'key':list('abd'),
                       'date2':[11,2,33]})
    print(df1)
    print(df2)
    print(pd.merge(df1, df2, left_index=True, right_index=True, suffixes=('_1', '_2')))  
    print(df1.join(df2['date2']))
    print('-----')
    # suffixes=('_x', '_y')默认
    
    left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3'],
                         'key': ['K0', 'K1', 'K0', 'K1']})
    right = pd.DataFrame({'C': ['C0', 'C1'],
                          'D': ['D0', 'D1']},
                         index=['K0', 'K1'])
    print(left)
    print(right)
    print(left.join(right, on = 'key'))
    # 等价于pd.merge(left, right, left_on='key', right_index=True, how='left', sort=False);
    # left的‘key’和right的index
    

    输出结果:

         A   B
    K0  A0  B0
    K1  A1  B1
    K2  A2  B2
         C   D
    K0  C0  D0
    K2  C2  D2
    K3  C3  D3
         A   B    C    D
    K0  A0  B0   C0   D0
    K1  A1  B1  NaN  NaN
    K2  A2  B2   C2   D2
          A    B    C    D
    K0   A0   B0   C0   D0
    K1   A1   B1  NaN  NaN
    K2   A2   B2   C2   D2
    K3  NaN  NaN   C3   D3
    -----
       data1 key
    0      1   b
    1      3   b
    2      2   a
    3      4   c
    4      5   a
    5      9   a
    6      7   b
       date2 key
    0     11   a
    1      2   b
    2     33   d
       data1 key_1  date2 key_2
    0      1     b     11     a
    1      3     b      2     b
    2      2     a     33     d
       data1 key  date2
    0      1   b   11.0
    1      3   b    2.0
    2      2   a   33.0
    3      4   c    NaN
    4      5   a    NaN
    5      9   a    NaN
    6      7   b    NaN
    -----
        A   B key
    0  A0  B0  K0
    1  A1  B1  K1
    2  A2  B2  K0
    3  A3  B3  K1
         C   D
    K0  C0  D0
    K1  C1  D1
        A   B key   C   D
    0  A0  B0  K0  C0  D0
    1  A1  B1  K1  C1  D1
    2  A2  B2  K0  C0  D0
    3  A3  B3  K1  C1  D1
    

    四、pandas的连接concat与修补combine_first

    连接是指沿轴执行连接操作。

    (1)连接concat

    pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)

    --->>> 参数axis:

    # 连接:concat
    # pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)
    
    s1 = pd.Series([1,2,3])
    s2 = pd.Series([2,3,4])
    s3 = pd.Series([1,2,3],index=list('ach'))
    s4 = pd.Series([2,3,4],index=['b','e','d'])
    #print(s4)
    
    # 【参数axis】
    # concat连接s1和s2,
    # 参数axis=0,是行+行,返回series
    sc = pd.concat([s1,s2])
    print(sc,type(sc))
    # concat连接s3和s4
    sc2 = pd.concat([s3,s4]) 
    print(sc2.sort_index()) # 对连接的series的index排序
    print('--------------------')
    
    # 参数axis=1,是列+列,返回dataframe
    df = pd.concat([s1,s2],axis=1)
    print(df,type(df))
    

    输出结果:

    0    1
    1    2
    2    3
    0    2
    1    3
    2    4
    dtype: int64 <class 'pandas.core.series.Series'>
    a    1
    b    2
    c    2
    d    4
    e    3
    h    3
    dtype: int64
    --------------------
       0  1
    0  1  2
    1  2  3
    2  3  4 <class 'pandas.core.frame.DataFrame'>
    

    --->>> 参数join和join_axes,表示连接方式:

    # 连接方式:join,join_axes
    
    s1 = pd.Series([1,2,3],index=list('abc'))
    s2 = pd.Series([2,3,4],index=list('bcd'))
    print(s1)
    print(s2)
    print('---------------')
    
    #【参数join】
    # 参数join默认为outer,取联合;join为inner取交集。
    print(pd.concat([s1,s2],axis=1,join='inner'))
    print('---------------')
    
    # 【参数join_axes】
    # 参数join_axes默认为None,若定义join_axes,可以指定联合的index
    print(pd.concat([s1,s2],axis=1,join_axes=[['a','b','c']]))
    

    输出结果:

    a    1
    b    2
    c    3
    dtype: int64
    b    2
    c    3
    d    4
    dtype: int64
    ---------------
       0  1
    b  2  2
    c  3  3
    ---------------
       0    1
    a  1  NaN
    b  2  2.0
    c  3  3.0
    

    --->>> 参数keys:

    # 覆盖列名:keys
    
    s1 = pd.Series([1,2,3],index=list('abc'))
    s2 = pd.Series([2,3,4],index=list('ejh'))
    
    sc = pd.concat([s1,s2])
    print(sc)
    
    # 【参数keys】
    # 参数keys默认None;
    # 若定义keys参数,以序列形式,可以使用传递的键作为最外层构建层次索引
    sc = pd.concat([s1,s2],keys=['one','two'])
    print(sc,type(sc))
    print(sc.index)
    
    # axis=1,且利用key参数覆盖列名;
    sc2 = pd.concat([s1,s2],axis=1,keys=['one','two'])
    print(sc2,type(sc2))
    

    输出结果:

    a    1
    b    2
    c    3
    e    2
    j    3
    h    4
    dtype: int64
    one  a    1
         b    2
         c    3
    two  e    2
         j    3
         h    4
    dtype: int64 <class 'pandas.core.series.Series'>
    MultiIndex(levels=[['one', 'two'], ['a', 'b', 'c', 'e', 'h', 'j']],
               labels=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 3, 5, 4]])
       one  two
    a  1.0  NaN
    b  2.0  NaN
    c  3.0  NaN
    e  NaN  2.0
    h  NaN  4.0
    j  NaN  3.0 <class 'pandas.core.frame.DataFrame'>
    

    (2)修补pd.combine_first()

    # 修补 pd.combine_first()
    
    df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],[np.nan, 7., np.nan]])
    df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],index=[1, 2])
    print(df1)
    print(df2)
    print('----------------------')
    
    print(df1.combine_first(df2))
    # pd.combine_first()修补,根据index,用df2将df1的空值替代上
    # 如果df2的index多于df1,则更新到df1上,比如index=['a',1]
    print('----------------------')
    
    df1.update(df2)
    print(df1)
    # update,直接df2覆盖df1,相同index位置
    

    输出结果:

         0    1    2
    0  NaN  3.0  5.0
    1 -4.6  NaN  NaN
    2  NaN  7.0  NaN
          0    1    2
    1 -42.6  NaN -8.2
    2  -5.0  1.6  4.0
    ----------------------
         0    1    2
    0  NaN  3.0  5.0
    1 -4.6  NaN -8.2
    2 -5.0  7.0  4.0
    ----------------------
          0    1    2
    0   NaN  3.0  5.0
    1 -42.6  NaN -8.2
    2  -5.0  1.6  4.0
    

    五、pandas的去重及替换

    (1)去重.duplicated

    # 去重 .duplicated
    
    # 创建一个含有重复元素的Series
    s = pd.Series([1,1,1,1,2,2,2,3,4,5,5,5,5])
    print(s)
    print('-------------')
    
    # duplicated()去重
    print(s.duplicated()) # 判断是否重复,返回布尔型
    print(s[s.duplicated()==False]) # 输出=False的,也就是不重复的
    print('------------')
    
    # drop.duplicates移除重复
    # 参数inplace,表是否替换原值,默认False不替换
    s_re = s.drop_duplicates()
    print(s_re)
    print('---------------')
    print('---------------')
    
    # Dataframe中使用duplicated
    # 创建一个含有重复元素的dataframe
    df = pd.DataFrame({'key1':['a','a',3,4,5],
                       'key2':['a','a','b','b','c']})
    print(df)
    print('---------------')
    print(df.duplicated()) 
    # 判断是aa是否重复,3b是否重复,是key1+key2结合一起判断的
    print(df['key2'].duplicated()) # 单判断key2这列的元素是否重复
    

    输出结果:

    0     1
    1     1
    2     1
    3     1
    4     2
    5     2
    6     2
    7     3
    8     4
    9     5
    10    5
    11    5
    12    5
    dtype: int64
    -------------
    0     False
    1      True
    2      True
    3      True
    4     False
    5      True
    6      True
    7     False
    8     False
    9     False
    10     True
    11     True
    12     True
    dtype: bool
    0    1
    4    2
    7    3
    8    4
    9    5
    dtype: int64
    ------------
    0    1
    4    2
    7    3
    8    4
    9    5
    dtype: int64
    ---------------
    ---------------
      key1 key2
    0    a    a
    1    a    a
    2    3    b
    3    4    b
    4    5    c
    ---------------
    0    False
    1     True
    2    False
    3    False
    4    False
    dtype: bool
    0    False
    1     True
    2    False
    3     True
    4    False
    Name: key2, dtype: bool
    

    (2)替换.replace

    # 替换 .replace
    
    s = pd.Series(list('ascaazsd'))
    print(s)
    print('---------')
    print(s.replace('a', np.nan)) # 用np.nan替换字符串"a"
    print('---------')
    # 可一次性替换一个值或多个值
    print(s.replace(['a','s'] ,np.nan))
    print('---------')
    # 可传入列表或字典
    print(s.replace({'a':'hello world!','s':123}))
    # 'a':'hello world!' → a 用hello world替换
    

    输出结果:

    0    a
    1    s
    2    c
    3    a
    4    a
    5    z
    6    s
    7    d
    dtype: object
    ---------
    0    NaN
    1      s
    2      c
    3    NaN
    4    NaN
    5      z
    6      s
    7      d
    dtype: object
    ---------
    0    NaN
    1    NaN
    2      c
    3    NaN
    4    NaN
    5      z
    6    NaN
    7      d
    dtype: object
    ---------
    0    hello world!
    1             123
    2               c
    3    hello world!
    4    hello world!
    5               z
    6             123
    7               d
    dtype: object
    

    六、数据分组groupby(重点掌握)

    分组统计,groupby功能:① 根据某些条件将数据拆分成组;② 对每个组独立应用函数;③ 将结果合并到一个数据结构中。

    Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。

    *df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, *kwargs)

    --->>> 分组:

    # 分组 - groupby()
    
    df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                       'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                       'C' : np.random.randn(8),
                       'D' : np.random.randn(8)})
    print(df)
    print('------')
    
    print(df.groupby('A'),type(df.groupby('A')))
    print('------')
    # 直接分组得到一个groupby对象,是一个中间数据,没有进行计算
    
    a = df.groupby('A').mean() # 以A分组,算平均值
    print(a,type(a))
    print('------')
    
    b = df.groupby(['A','B']).mean() # 以A、B分组,算平均值
    print(b,type(b))
    print('------')
    
    c = df.groupby('A')['D'].mean() # 以A分组,再取个D列求D的平均值
    print(c)
    # 通过分组后的计算,得到一个新的dataframe
    # 默认axis = 0,以行来分组
    # 可单个或多个([])列分组
    

    输出结果:

         A      B         C         D
    0  foo    one -0.644577  1.118908
    1  bar    one  1.179229 -0.386515
    2  foo    two -1.060731  0.536817
    3  bar  three  1.151450 -1.321295
    4  foo    two  0.388789  2.147647
    5  bar    two  0.059214  1.008346
    6  foo    one  1.364315 -0.617321
    7  foo  three -0.834223 -0.671149
    ------
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000001B5FCD8A7B8> <class 'pandas.core.groupby.groupby.DataFrameGroupBy'>
    ------
                C         D
    A                      
    bar  0.796631 -0.233155
    foo -0.157285  0.502980 <class 'pandas.core.frame.DataFrame'>
    ------
                      C         D
    A   B                        
    bar one    1.179229 -0.386515
        three  1.151450 -1.321295
        two    0.059214  1.008346
    foo one    0.359869  0.250794
        three -0.834223 -0.671149
        two   -0.335971  1.342232 <class 'pandas.core.frame.DataFrame'>
    ------
    A
    bar   -0.233155
    foo    0.502980
    Name: D, dtype: float64
    

    --->>> 分组迭代对象:

    # 分组 - 可迭代对象
    
    # 创建df
    df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
    print(df)
    print(df.groupby('X'), type(df.groupby('X')))  
    print('-----')
    
    
    # 可迭代对象
    print(list(df.groupby('X')), '→ 可迭代对象,直接生成list\n')
    print(list(df.groupby('X'))[0], '→ 以元祖形式显示\n')
    for n,g in df.groupby('X'):
        print(n)
        print(g)
        print('###')
    print('-----')
    # n是组名,g是分组后的Dataframe
    
    # .get_group()提取分组后的组
    print(df.groupby(['X']).get_group('A'),'\n') # 提取分组后的A组
    print(df.groupby(['X']).get_group('B'),'\n') # 提取分组后的B组
    print('-----')
    
    
    # .groups:将分组后的groups转为dict
    # 可以字典索引方法来查看groups里的元素
    grouped = df.groupby(['X'])
    print(grouped)
    print(grouped.groups) # 以X列分组后用.grouped转为字典dict
    print(grouped.groups['A'],type(grouped.groups['A']))  # 提取字典里的key为A的元素
    print('-----')
    
    
    # .size():查看分组后的长度
    sz = grouped.size() 
    print(sz,type(sz))
    print('----------------------------------')
    
    
    df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                       'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                       'C' : np.random.randn(8),
                       'D' : np.random.randn(8)})
    print(df)
    print('---------')
    grouped = df.groupby(['A','B']).groups  # 以A、B列分组,分组后组成dict
    print(grouped,type(grouped))
    print('----')
    print(grouped[('foo', 'three')]) # 提取grouped字典key为('foo', 'three')的元素
    

    输出结果:

       X  Y
    0  A  1
    1  B  4
    2  A  3
    3  B  2
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000001B5FCDB8DA0> <class 'pandas.core.groupby.groupby.DataFrameGroupBy'>
    -----
    [('A',    X  Y
    0  A  1
    2  A  3), ('B',    X  Y
    1  B  4
    3  B  2)] → 可迭代对象,直接生成list
    
    ('A',    X  Y
    0  A  1
    2  A  3) → 以元祖形式显示
    
    A
       X  Y
    0  A  1
    2  A  3
    ###
    B
       X  Y
    1  B  4
    3  B  2
    ###
    -----
       X  Y
    0  A  1
    2  A  3 
    
       X  Y
    1  B  4
    3  B  2 
    
    -----
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000001B5FCD2FE48>
    {'A': Int64Index([0, 2], dtype='int64'), 'B': Int64Index([1, 3], dtype='int64')}
    Int64Index([0, 2], dtype='int64') <class 'pandas.core.indexes.numeric.Int64Index'>
    -----
    X
    A    2
    B    2
    dtype: int64 <class 'pandas.core.series.Series'>
    ----------------------------------
         A      B         C         D
    0  foo    one -1.145245  0.282188
    1  bar    one  1.098816 -1.229021
    2  foo    two -0.202471  1.313067
    3  bar  three  0.423064 -0.944102
    4  foo    two  1.035012 -0.159363
    5  bar    two  2.586997 -0.870078
    6  foo    one  0.549764 -0.323518
    7  foo  three -2.402178  0.990989
    ---------
    {('foo', 'one'): Int64Index([0, 6], dtype='int64'), ('foo', 'three'): Int64Index([7], dtype='int64'), ('bar', 'three'): Int64Index([3], dtype='int64'), ('foo', 'two'): Int64Index([2, 4], dtype='int64'), ('bar', 'one'): Int64Index([1], dtype='int64'), ('bar', 'two'): Int64Index([5], dtype='int64')} <class 'dict'>
    ----
    Int64Index([7], dtype='int64')
    

    --->>> 其他轴上的分组:

    # 其他轴上的分组
    
    df = pd.DataFrame({'data1':np.random.rand(2),
                      'data2':np.random.rand(2),
                      'key1':['a','b'],
                      'key2':['one','two']})
    print(df)
    print(df.dtypes)
    print('-----')
    
    # 按照值类型分列
    for n,p in df.groupby(df.dtypes, axis=1):
        print(n)
        print(p)
        print('##')
    

    输出结果:

          data1     data2 key1 key2
    0  0.269405  0.236738    a  one
    1  0.000449  0.503876    b  two
    data1    float64
    data2    float64
    key1      object
    key2      object
    dtype: object
    -----
    float64
          data1     data2
    0  0.269405  0.236738
    1  0.000449  0.503876
    ##
    object
      key1 key2
    0    a  one
    1    b  two
    ##
    

    --->>> 过字典或者Series分组:(特定分组的时候会比较方便)

    # 通过字典或者Series分组
    
    df = pd.DataFrame(np.arange(16).reshape(4,4),
                      columns = ['a','b','c','d'])
    print(df)
    print('-----')
    
    # 创建字典
    dic = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
    print(dic,type(dic))
    # 通过字典分组
    dic_by = df.groupby(dic,axis = 1).sum()
    print(dic_by)
    print('-----')
    # dic中,a、b列对应的为one,c、d列对应的为two,以字典来分组
    
    
    # 创建series
    s = pd.Series(dic)
    print(s,'\n')
    print(s.groupby(s).count())
    # s中,index中a、b对应的为one,c、d对应的为two,以Series来分组
    

    输出结果:

        a   b   c   d
    0   0   1   2   3
    1   4   5   6   7
    2   8   9  10  11
    3  12  13  14  15
    -----
    {'d': 'two', 'b': 'one', 'c': 'two', 'a': 'one', 'e': 'three'} <class 'dict'>
       one  two
    0    1    5
    1    9   13
    2   17   21
    3   25   29
    -----
    a      one
    b      one
    c      two
    d      two
    e    three
    dtype: object 
    
    one      2
    three    1
    two      2
    dtype: int64
    

    --->>> 通过函数分组:

    # 通过函数分组
    
    df = pd.DataFrame(np.arange(16).reshape(4,4),
                      columns = ['a','b','c','d'],
                     index = ['abc','bcd','aa','b'])
    print(df,'\n')
    print(df.groupby(len).sum())
    # 按照字母长度分组
    
          a   b   c   d
    abc   0   1   2   3
    bcd   4   5   6   7
    aa    8   9  10  11
    b    12  13  14  15 
    
        a   b   c   d
    1  12  13  14  15
    2   8   9  10  11
    3   4   6   8  10
    

    --->>> 分组计算函数方法:

    # 分组计算函数方法
    
    s = pd.Series([1, 2, 3, 10, 20, 30], index = [1, 2, 3, 1, 2, 3])
    print(s,'\n')
    
    grouped = s.groupby(level=0)
    print(grouped,'\n')
    # 唯一索引用.groupby(level=0),将同一个index的分为一组
    
    print(grouped.first(),'→ first:非NaN的第一个值\n')
    print(grouped.last(),'→ last:非NaN的最后一个值\n')
    print(grouped.sum(),'→ sum:非NaN的和\n')
    print(grouped.mean(),'→ mean:非NaN的平均值\n')
    print(grouped.median(),'→ median:非NaN的算术中位数\n')
    print(grouped.count(),'→ count:非NaN的值\n')
    print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
    print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
    print(grouped.prod(),'→ prod:非NaN的积\n')
    

    输出结果:

    1     1
    2     2
    3     3
    1    10
    2    20
    3    30
    dtype: int64 
    
    <pandas.core.groupby.groupby.SeriesGroupBy object at 0x000001B5FDE28D30> 
    
    1    1
    2    2
    3    3
    dtype: int64 → first:非NaN的第一个值
    
    1    10
    2    20
    3    30
    dtype: int64 → last:非NaN的最后一个值
    
    1    11
    2    22
    3    33
    dtype: int64 → sum:非NaN的和
    
    1     5.5
    2    11.0
    3    16.5
    dtype: float64 → mean:非NaN的平均值
    
    1     5.5
    2    11.0
    3    16.5
    dtype: float64 → median:非NaN的算术中位数
    
    1    2
    2    2
    3    2
    dtype: int64 → count:非NaN的值
    
    1    1
    2    2
    3    3
    dtype: int64 → min、max:非NaN的最小值、最大值
    
    1     6.363961
    2    12.727922
    3    19.091883
    dtype: float64 → std,var:非NaN的标准差和方差
    
    1    10
    2    40
    3    90
    dtype: int64 → prod:非NaN的积
    

    --->>> 多函数计算:agg()

    # 多函数计算:agg()
    # 多函数计算可以让分组数据同时计算两个以上的统计
    
    df = pd.DataFrame({'a':[1,1,2,2],
                      'b':np.random.rand(4),
                      'c':np.random.rand(4),
                      'd':np.random.rand(4),})
    print(df,'\n')
    
    print(df.groupby('a').agg(['mean',np.sum]))
    print(df.groupby('a')['b'].agg({'result1':np.mean,
                                   'result2':np.sum}))
    # 函数写法可以用str,或者np.方法
    # 可以通过list,dict传入,当用dict时,key名为columns
    

    输出结果:

       a         b         c         d
    0  1  0.689856  0.212391  0.575196
    1  1  0.516206  0.871239  0.340175
    2  2  0.440666  0.428301  0.573359
    3  2  0.211181  0.900975  0.845924 
    
              b                   c                   d          
           mean       sum      mean       sum      mean       sum
    a                                                            
    1  0.603031  1.206062  0.541815  1.083630  0.457686  0.915371
    2  0.325924  0.651847  0.664638  1.329276  0.709641  1.419282
        result2   result1
    a                    
    1  1.206062  0.603031
    2  0.651847  0.325924
    

    七、分组转换及一般性“拆分-应用-合并”

    (1)数据分组转换transform

    # 数据分组转换,transform
    
    df = pd.DataFrame({'data1':np.random.rand(5),
                      'data2':np.random.rand(5),
                      'key1':list('aabba'),
                      'key2':['one','two','one','two','one']})
    print(df,'\n')
    
    k_mean = df.groupby('key1').mean() # 以key1分组,求平均值
    print(k_mean,'\n')
    
    print(pd.merge(df,k_mean,left_on='key1',right_index=True).add_prefix('mean_'))  # .add_prefix('mean_'):添加前缀
    print('---------------')
    # 通过分组、合并,得到一个包含均值的Dataframe
    
    print(df.groupby('key2').mean(),'\n') # 按照key2分组求均值
    print(df.groupby('key2').transform(np.mean))
    # data1、data2每个位置元素取对应分组列的均值
    # 字符串不能进行计算
    

    输出结果:

          data1     data2 key1 key2
    0  0.295972  0.857439    a  one
    1  0.934285  0.278705    a  two
    2  0.302457  0.844987    b  one
    3  0.248708  0.549459    b  two
    4  0.978329  0.691800    a  one 
    
             data1     data2
    key1                    
    a     0.736195  0.609315
    b     0.275582  0.697223 
    
       mean_data1_x  mean_data2_x mean_key1 mean_key2  mean_data1_y  mean_data2_y
    0      0.295972      0.857439         a       one      0.736195      0.609315
    1      0.934285      0.278705         a       two      0.736195      0.609315
    4      0.978329      0.691800         a       one      0.736195      0.609315
    2      0.302457      0.844987         b       one      0.275582      0.697223
    3      0.248708      0.549459         b       two      0.275582      0.697223
    ---------------
             data1     data2
    key2                    
    one   0.525586  0.798075
    two   0.591497  0.414082 
    
          data1     data2
    0  0.525586  0.798075
    1  0.591497  0.414082
    2  0.525586  0.798075
    3  0.591497  0.414082
    4  0.525586  0.798075
    

    (2)一般化groupby方法:apply(运用较广泛)

    # 一般化Groupby方法:apply
    # apply直接运行其中的函数
    
    
    df = pd.DataFrame({'data1':np.random.rand(5),
                      'data2':np.random.rand(5),
                      'key1':list('aabba'),
                      'key2':['one','two','one','two','one']})
    
    print(df.groupby('key1').apply(lambda x: x.describe()))
    # apply直接运行其中的函数
    # 这里为匿名函数,直接描述分组后的统计量
    
    def f_df1(d,n):
        return(d.sort_index()[:n])
    def f_df2(d,k1):
        return(d[k1])
    print(df.groupby('key1').apply(f_df1,2),'\n')
    print(df.groupby('key1').apply(f_df2,'data2'))
    print(type(df.groupby('key1').apply(f_df2,'data2')))
    # f_df1函数:返回排序后的前n行数据
    # f_df2函数:返回分组后表的k1列,结果为Series,层次化索引
    # 直接运行f_df函数
    # 参数直接写在后面,也可以为.apply(f_df,n = 2))
    

    输出结果:

                   data1     data2
    key1                          
    a    count  3.000000  3.000000
         mean   0.260004  0.604611
         std    0.423720  0.200435
         min    0.007524  0.397114
         25%    0.015412  0.508344
         50%    0.023299  0.619574
         75%    0.386244  0.708360
         max    0.749189  0.797146
    b    count  2.000000  2.000000
         mean   0.379854  0.639659
         std    0.043777  0.308873
         min    0.348899  0.421253
         25%    0.364377  0.530456
         50%    0.379854  0.639659
         75%    0.395332  0.748862
         max    0.410809  0.858065
               data1     data2 key1 key2
    key1                                
    a    0  0.023299  0.397114    a  one
         1  0.007524  0.797146    a  two
    b    2  0.410809  0.421253    b  one
         3  0.348899  0.858065    b  two 
    
    key1   
    a     0    0.397114
          1    0.797146
          4    0.619574
    b     2    0.421253
          3    0.858065
    Name: data2, dtype: float64
    <class 'pandas.core.series.Series'>
    

    八、透视表及交叉表

    类似excel数据透视 - pivot table / crosstab

    (1)透视表pivot_table

    透视表就是做数据透视。

    pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')

    # 透视表:pivot_table
    # pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
    
    date = ['2017-5-1','2017-5-2','2017-5-3']*3
    rng = pd.to_datetime(date)
    df = pd.DataFrame({'date':rng,
                       'key':list('abcdabcda'),
                      'values':np.random.rand(9)*10})
    print(df)
    print('-----')
    
    print(pd.pivot_table(df,values='values',index='date',columns='key',aggfunc=np.sum),'\n')
    # data:DataFrame对象
    # values:要聚合的列或列的列表
    # index:数据透视表的index,从原数据的列中筛选
    # columns:数据透视表的columns,从原数据的列中筛选
    # aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
    
    print(pd.pivot_table(df, values = 'values', index = ['date','key'], aggfunc=len))
    # 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
    # aggfunc=len(或者count):计数
    

    输出结果:

            date key    values
    0 2017-05-01   a  1.978948
    1 2017-05-02   b  6.444399
    2 2017-05-03   c  5.816060
    3 2017-05-01   d  4.127823
    4 2017-05-02   a  7.059673
    5 2017-05-03   b  4.657516
    6 2017-05-01   c  3.127164
    7 2017-05-02   d  0.198809
    8 2017-05-03   a  1.435535
    -----
    key                a         b         c         d
    date                                              
    2017-05-01  1.978948       NaN  3.127164  4.127823
    2017-05-02  7.059673  6.444399       NaN  0.198809
    2017-05-03  1.435535  4.657516  5.816060       NaN 
    
                    values
    date       key        
    2017-05-01 a       1.0
               c       1.0
               d       1.0
    2017-05-02 a       1.0
               b       1.0
               d       1.0
    2017-05-03 a       1.0
               b       1.0
               c       1.0
    

    (2)交叉表crosstab

    交叉表做因子频率计算。

    pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)

    # 交叉表:crosstab,统计频率的时候用交叉表,如字符串只能计算频率
    # 默认情况下,crosstab计算因子的频率表,比如用于str的数据透视分析
    # pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
    
    df = pd.DataFrame({'A': [1, 2, 2, 2, 2],
                       'B': [3, 3, 4, 4, 4],
                       'C': [1, 1, np.nan, 1, 1]})
    print(df)
    print('-----')
    
    print(pd.crosstab(df['A'],df['B']))
    #print('-----')
    # 如果crosstab只接收两个Series,它将提供一个频率表。
    # 用A的唯一值,统计B唯一值的出现次数
    # 返回的频率表意思:B=3,A=1的频率为1,以此类推。
    
    print(pd.crosstab(df['A'],df['B'],normalize=True))
    print('-----')
    # normalize:默认False,将所有值除以值的总和进行归一化 → 为True时候显示百分比
    # 返回的频率表是B=3,A=1的频率为1,总和为1+0+1+3=5,1/5=0.2
    
    print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum))
    print('-----')
    # values:可选,根据因子聚合的值数组
    # aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算
    # 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
    
    print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum, margins=True))
    # margins:布尔值,默认值False,添加行/列边距(小计求和)
    

    输出结果:

       A  B    C
    0  1  3  1.0
    1  2  3  1.0
    2  2  4  NaN
    3  2  4  1.0
    4  2  4  1.0
    -----
    B  3  4
    A      
    1  1  0
    2  1  3
    B    3    4
    A          
    1  0.2  0.0
    2  0.2  0.6
    -----
    B    3    4
    A          
    1  1.0  NaN
    2  1.0  2.0
    -----
    B      3    4  All
    A                 
    1    1.0  NaN  1.0
    2    1.0  2.0  3.0
    All  2.0  2.0  4.0
    

    九、数据读取

    (1)读取普通分隔数据read_table

    读取普通分隔数据read_table,主要用于读取简单的数据,可以读取txt,csv。

    # 读取普通分隔数据:read_table
    # 可以读取txt,csv
    
    import os # 调用os模块
    os.chdir(r'C:\Users\Yeung\Desktop')  # 导入路径
    
    data1 = pd.read_table('data1.txt', delimiter=',')
    print(data1,'\n')
    # delimiter:用于拆分的字符,也可以用sep:sep = ','
    data2 = pd.read_table('data1.txt',delimiter=',',header=1)
    print(data2,'\n')
    # 参数header:表示用做列名的序号,默认为0(第一行),这里data2指定用第二行为列名
    # 参数index_col:表示指定某列为行索引,默认index_col=None,自动用0, 1, 2,.....数字作索引
    
    # read_table主要用于读取简单的数据,txt/csv(使用较少)
    

    输出结果:

       va1  va2  va3  va4
    0    1    2    3    4
    1    2    3    4    5
    2    3    4    5    6
    3    4    5    6    7 
    
       1  2  3  4
    0  2  3  4  5
    1  3  4  5  6
    2  4  5  6  7 
    

    (2)读取csv数据read_csv

    csv数据其实就是逗号分隔符类的数据。

    # 读取csv数据:read_csv
    # 先熟悉一下excel怎么导出csv——excel另存csv即可,要注意选择的编码是什么
    
    data2 = pd.read_csv('data2.csv',engine = 'python',encoding= 'utf8')
    print(data2.head(20))
    print(type(data2))
    # 参数engine:使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
    # 参数encoding:指定字符集类型,即编码,通常指定为'utf8';如果发现读取有问题就把这个参数加上
    
    # 大多数情况先将excel导出csv,再读取
    

    (3)读取excel数据read_excel

    数据是报表excel一般是已经处理过的数据。

    # 读取excel数据:read_excel
    
    data3 = pd.read_excel('data3.xlsx',sheet_name='中国人民共和国地市级党委书记数据库(2000-10)',header=0)
    print(data3)
    # io :文件路径。
    # sheet_name:返回多表使用sheetname=[0,1],若sheetname=None是返回全表 → ① int/string 返回的是dataframe ②而none和list返回的是dict
    # header:指定列名行,默认0,即取第一行
    # index_col:指定列为索引列,也可以使用u”strings”
    

    输出结果:


    输出结果截图.png

    相关文章

      网友评论

        本文标题:笔记:Python之Pandas的使用技巧

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