zoukankan      html  css  js  c++  java
  • 04. Pandas 3| 数值计算与统计、合并连接去重分组透视表文件读取

    1.数值计算和统计基础

    常用数学、统计方法

    数值计算和统计基础

    基本参数:axis、skipna

    df.mean(axis=1,skipna=False)  -->> axis=1是按行来进行统计; 默认按列统计(axis默认为0,可不写); skipna=False是不忽略,显示NaN,默认为True,即忽略NaN.

    >>> import numpy as np
    >>> import pandas as pd
    >>> df = pd.DataFrame({'key1':[4,5,3,np.nan,2],  # np.nan :空值 
    ... 'key2':[1,2,np.nan,4,5],
    ... 'key3':[1,2,3,'j','k']}, #字符串
    ... index = ['a','b','c','d','e'])
    >>> print(df)
       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
    >>> print(df['key1'].dtype, df['key2'].dtype, df['key3'].dtype)
    float64 float64 object  (object是python的对象)

    >>> print(df.mean(),type(df.mean)) #.mean()计算均值(默认按列),只统计数字列 ,key3为object对象不统计。

     key1 3.5
     key2 3.0
     dtype: float64  <class 'pandas.core.series.Series'>

     >>>

    >>> print('单独统计一列:',df['key2'].mean())  # .mean()计算均值  # 可以通过索引单独统计一列;  
    单独统计一列: 3.0
    >>>
    >>> m2 = df.mean(axis=1)  # 只统计数字列   #axis参数:默认为0,以列来计算, axis=1,以行来计算,这里就按照行来汇总了,也是只统计数字那行
    >>> print(m2)
    a    2.5
    b    3.5
    c    3.0
    d    4.0
    e    3.5
    dtype: float64
    >>>

     >>> print(df.mean(axis=1, skipna=False)) #以行来算;  skipna参数是是否忽略NaN,默认True忽略结果同上;False是有NaN的行,就直接显示NaN了不忽略它。
     a 2.5
     b 3.5
     c NaN
     d NaN
     e 3.5
     dtype: float64
    >>>

    >>> m3 = df.mean(skipna=False) #按列来算 >>> print(m3)
    key1   NaN
    key2   NaN
    dtype: float64
    >>>

    主要数学计算方法,可用于Series和DataFrame(1)

    .count( )统计非NaN值的数量、.min()、.max()、 .quantile(q=0.5)统计分位数、 .sum()求和、 .mean()平均值 、.median()中位数 、.std() 标准差、.var()方差

    >>> df = pd.DataFrame({'key1':np.arange(10),
    ...                   'key2':np.random.rand(10)*10})
    >>> print(df)
        key1      key2
    0     0  7.556713
    1     1  8.650398
    2     2  4.692490
    3     3  0.275988
    4     4  2.710686
    5     5  5.130423
    6     6  3.638846
    7     7  2.989476
    8     8  7.105496
    9     9  0.907657
    >>> print(df.count(),'→ count统计非Na值的数量
    ')
    key1    10
    key2    10
    dtype: int64 → count统计非Na值的数量
    
    >>> print(df.min(),'→ min统计最小值
    ',df['key2'].max(),'→ max统计最大值
    ')
    key1    0.000000
    key2    0.275988
    dtype: float64 → min统计最小值
     8.650397903041455 → max统计最大值
    
    >>> print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置
    ') #q=0.75,分位数就是总共数的3/4位置的那个数
    key1    6.750000
    key2    6.611727
    Name: 0.75, dtype: float64 → quantile统计分位数,参数q确定位置
    
    >>> print(df.sum(),'→ sum求和
    ')
    key1    45.000000
    key2    43.658172
    dtype: float64 → sum求和
    
    >>> print(df.mean(),'→ mean求平均值
    ')
    key1    4.500000
    key2    4.365817
    dtype: float64 → mean求平均值
    
    >>> print(df.median(),'→ median求算数中位数,50%分位数
    ')
    key1    4.500000
    key2    4.165668
    dtype: float64 → median求算数中位数,50%分位数
    
    >>> print(df.std(),'
    ',df.var(),'→ std,var分别求标准差,方差
    ')
    key1    3.027650
    key2    2.800485
    dtype: float64
     key1    9.166667
    key2    7.842718
    dtype: float64 → std,var分别求标准差,方差
    
    >>> print(df.skew(),'→ skew样本的偏度
    ')  #偏度和峰度是用来进行一致性检验的。
    key1    0.000000
    key2    0.094214
    dtype: float64 → skew样本的偏度
    
    >>> print(df.kurt(),'→ kurt样本的峰度
    ')
    key1   -1.200000
    key2   -1.033864
    dtype: float64 → kurt样本的峰度
    
    >>>

    主要数学计算方法,可用于Series和DataFrame(2)

    df.cumsum()累积求和、 df.cumprod()累计求积、   df.cummax()累计最大值,出现最大值了就一直是那个最大值了、  cummin()累计最小值 

    >>> df['key1_s'] = df['key1'].cumsum() #样本的累计和,默认列。下面这4个赋值,给df添加了4个字段。
    >>> df['key2_s'] = df['key2'].cumsum()
    >>> print(df,'→ cumsum样本的累计和
    ')
        key1    key2     key1_s   key2_s
    0     0  7.556713       0   7.556713
    1     1  8.650398       1  16.207111
    2     2  4.692490       3  20.899601
    3     3  0.275988       6  21.175589
    4     4  2.710686      10  23.886275
    5     5  5.130423      15  29.016698
    6     6  3.638846      21  32.655544
    7     7  2.989476      28  35.645019
    8     8  7.105496      36  42.750515
    9     9  0.907657      45  43.658172 → cumsum样本的累计和
    
    >>> df['key1_p'] = df['key1'].cumprod() #样本的累计积,默认列
    >>> df['key2_p'] = df['key2'].cumprod()
    >>> print(df,'→ cumprod样本的累计积
    ')
        key1   key2     key1_s     key2_s  key1_p        key2_p
    0     0  7.556713       0   7.556713       0      7.556713
    1     1  8.650398       1  16.207111       0     65.368572
    2     2  4.692490       3  20.899601       0    306.741386
    3     3  0.275988       6  21.175589       0     84.656944
    4     4  2.710686      10  23.886275       0    229.478404
    5     5  5.130423      15  29.016698       0   1177.321217
    6     6  3.638846      21  32.655544       0   4284.090351
    7     7  2.989476      28  35.645019       0  12807.184945
    8     8  7.105496      36  42.750515       0  91001.397399
    9     9  0.907657      45  43.658172       0  82598.051142 → cumprod样本的累计积
    
    >>> print(df.cummax(),'
    ',df.cummin(),'→ cummax,cummin分别求累计最大值,累计最小值
    ') #累计最大值和最小值会直接填充之前的key1、key2
       key1      key2  key1_s     key2_s  key1_p        key2_p
    0   0.0  7.556713     0.0   7.556713     0.0      7.556713
    1   1.0  8.650398     1.0  16.207111     0.0     65.368572
    2   2.0  8.650398     3.0  20.899601     0.0    306.741386
    3   3.0  8.650398     6.0  21.175589     0.0    306.741386
    4   4.0  8.650398    10.0  23.886275     0.0    306.741386
    5   5.0  8.650398    15.0  29.016698     0.0   1177.321217
    6   6.0  8.650398    21.0  32.655544     0.0   4284.090351
    7   7.0  8.650398    28.0  35.645019     0.0  12807.184945
    8   8.0  8.650398    36.0  42.750515     0.0  91001.397399
    9   9.0  8.650398    45.0  43.658172     0.0  91001.397399
        key1      key2  key1_s    key2_s  key1_p    key2_p
    0   0.0  7.556713     0.0  7.556713     0.0  7.556713
    1   0.0  7.556713     0.0  7.556713     0.0  7.556713
    2   0.0  4.692490     0.0  7.556713     0.0  7.556713
    3   0.0  0.275988     0.0  7.556713     0.0  7.556713  #出现最小值了就一直累计那个最小值
    4   0.0  0.275988     0.0  7.556713     0.0  7.556713
    5   0.0  0.275988     0.0  7.556713     0.0  7.556713
    6   0.0  0.275988     0.0  7.556713     0.0  7.556713
    7   0.0  0.275988     0.0  7.556713     0.0  7.556713
    8   0.0  0.275988     0.0  7.556713     0.0  7.556713
    9   0.0  0.275988     0.0  7.556713     0.0  7.556713 → cummax,cummin分别求累计最大值,累计最小值
    
    >>>

    唯一值:.unique( ) 去掉重复的值

    s.unique() 

    >>> s = pd.Series(list('asdvasdcfgg'))
    >>> sq = s.unique() #得到一个只有唯一数值的数组,没有重复值了
    >>> 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
    >>> print(sq,type(sq))
    ['a' 's' 'd' 'v' 'c' 'f' 'g'] <class 'numpy.ndarray'>
    >>> print(pd.Series(sq))  # 通过pd.Series重新变成新的Series
    0    a
    1    s
    2    d
    3    v
    4    c
    5    f
    6    g
    dtype: object
    >>> sq.sort()
    >>> print(sq)
    ['a' 'c' 'd' 'f' 'g' 's' 'v']
    >>>

    值计数:.value_counts() 计算不同值出现的频率

    s.value_counts(sort = False)  # 也可以这样写:pd.value_counts(sc, sort = False), sort=False是不排序,sort默认为True降序。
    >>> sc = s.value_counts(sort = False)  # 也可以这样写:pd.value_counts(sc, sort = False)
    >>> print(sc)  # 得到一个新的Series,计算出不同值出现的频率; # sort参数:排序,默认为True降序,False是不排序。
    s    2
    d    2
    v    1
    f    1
    c    1
    g    2
    a    2
    dtype: int64
    >>>

    成员资格:.isin() 判断值是否在里边

    s.isin( [ 3, 12 ] ) 数值3和12是否在里边

    >>> s = pd.Series(np.arange(10,15))
    >>> df = pd.DataFrame({'key1':list('asdcbvasd'),
    ...                   'key2':np.arange(4,13)})
    >>> print(s)
    0    10
    1    11
    2    12
    3    13
    4    14
    dtype: int32
    >>> print(df)
      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
    >>> print('-----')
    -----
    >>>
    >>> print(s.isin([5,14]))
    0    False
    1    False
    2    False
    3    False
    4     True
    dtype: bool
    >>> print(df.isin(['a','bc','10',8]))
        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
    >>>

    2.文本数据

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

    2.1 通过str访问,且自动排除丢失/ NA值

    .str调用字符串方法 s.str.count('b')  .str.upper()  df.columns.str.upper()
    >>> 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)
    0          A
    1          b
    2          C
    3    bbhello
    4        123
    5        NaN
    6         hj
    dtype: object
    >>> print(df)
      key1  key2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    >>>
    >>> print(s.str.count('b'))  # 直接通过.str调用字符串方法 # 可以对Series、Dataframe使用 # 自动过滤NaN值
    0    0.0
    1    1.0
    2    0.0
    3    2.0
    4    0.0
    5    NaN
    6    0.0
    dtype: float64
    >>> print(df['key2'].str.upper())
    0     HEE
    1      FV
    2       W
    3    HIJA
    4     123
    5     NaN
    Name: key2, dtype: object
    >>>
    >>> df.columns = df.columns.str.upper()  # df.columns是一个Index对象,也可使用.str
    >>> print(df)
      KEY1  KEY2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    >>>

    2.2 字符串常用方法 - lower,upper,len,startswith,endswith,strip,replace,split

    f['key2'].str.upper()  .str.len()   .str.startswith('b')    .str.endswith('3')   .str.strip()去除字符串中空格
    df.columns.str.replace(' ', '-')   .str.split(','))   .str.split(',').str.get(1)  .str.split(',',expand=True)   
    s.str.split(',',expand=True,n=1) expand是将Series变为DataFrame,n=1是限制分割多少列
    ########字符串常用方法(一)
    >>> 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) 0 A 1 b 2 C 3 bbhello 4 123 5 NaN 6 hj dtype: object >>> print(df) key1 key2 0 a hee 1 b fv 2 c w 3 d hija 4 e 123 5 f NaN >>> >>> print(s.str.count('b')) 0 0.0 1 1.0 2 0.0 3 2.0 4 0.0 5 NaN 6 0.0 dtype: float64 >>> print(df['key2'].str.upper()) 0 HEE 1 FV 2 W 3 HIJA 4 123 5 NaN Name: key2, dtype: object >>> >>> df.columns = df.columns.str.upper() >>> print(df) KEY1 KEY2 0 a hee 1 b fv 2 c w 3 d hija 4 e 123 5 f NaN >>> >>> >>> >>> >>> >>> s = pd.Series(['A','b','bbhello','123',np.nan]) >>> print(s.str.lower(),'→ lower小写 ') 0 a 1 b 2 bbhello 3 123 4 NaN dtype: object → lower小写 >>> print(s.str.upper(),'→ lower大写 ') 0 A 1 B 2 BBHELLO 3 123 4 NaN dtype: object → lower大写 >>> print(s.str.len(),'→ len字符长度 ') 0 1.0 1 1.0 2 7.0 3 3.0 4 NaN dtype: float64 → len字符长度 >>> print(s.str.startswith('b'),'→ 判断起始是否为a ') 0 False 1 True 2 True 3 False 4 NaN dtype: object → 判断起始是否为a >>> print(s.str.endswith('3'),'→ 判断结束是否为3 ') 0 False 1 False 2 False 3 True 4 NaN dtype: object → 判断结束是否为3 >>> >>> >>>字符串常用方法(2) - strip >>> 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) 0 jack 1 jill 2 jesse 3 frank dtype: object >>> print(df) Column A Column B 0 1.134152 1.030622 1 -0.509581 -0.102576 2 1.033234 -1.170396 >>> >>> print(s.str.strip()) # 去除字符串中的空格 0 jack 1 jill 2 jesse 3 frank dtype: object >>> print(s.str.lstrip())  # 去除字符串中的左空格 0 jack 1 jill 2 jesse 3 frank dtype: object >>> print(s.str.rstrip())  # 去除字符串中的右空格 0 jack 1 jill 2 jesse 3 frank dtype: object >>> df.columns = df.columns.str.strip() # 这里去掉了columns的前后空格,但没有去掉中间空格 >>> print(df) Column A Column B 0 1.134152 1.030622 1 -0.509581 -0.102576 2 1.033234 -1.170396 >>> >>> >>># 字符串常用方法(3) - replace >>> df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '], ... index=range(3)) >>> df.columns = df.columns.str.replace(' ', '-') >>> print(df) -Column-A- -Column-B- 0 -0.721763 0.899423 1 1.129852 0.893515 2 -1.715414 -1.465260 >>> >>> df.columns = df.columns.str.replace('-','hehe',n=1) >>> print(df) heheColumn-A- heheColumn-B- 0 -0.721763 0.899423 1 1.129852 0.893515 2 -1.715414 -1.465260 >>> >>> >>># 字符串常用方法(4) - split、rsplit >>> s = pd.Series(['a,b,c','1,2,3',['a,,,c'],np.nan]) >>> print(s.str.split(',')) # 类似字符串的split 0 [a, b, c] 1 [1, 2, 3] 2 NaN 3 NaN dtype: object >>> print(s.str.split(',')[0]) ## 直接索引得到一个list ['a', 'b', 'c'] >>> >>> print(s.str.split(',').str[0]) 0 a 1 1 2 NaN 3 NaN dtype: object >>> print(s.str.split(',').str.get(1)) # 可以使用get或[]符号访问拆分列表中的元素 0 b 1 2 2 NaN 3 NaN dtype: object >>> >>> print(s.str.split(',',expand=True)) # 可以使用expand可以轻松扩展此操作以返回DataFrame;expand默认为False 0 1 2 0 a b c 1 1 2 3 2 NaN NaN NaN 3 NaN NaN NaN >>> print(s.str.split(',',expand=True,n=1)) # n参数限制分割数 0 1 0 a b,c 1 1 2,3 2 NaN NaN 3 NaN NaN >>> print(s.str.rsplit(',',expand=True,n=1)) # rsplit类似于split,反向工作,即从字符串的末尾到字符串的开头 0 1 0 a,b c 1 1,2 3 2 NaN NaN 3 NaN NaN >>>
    >>> df = pd.DataFrame({'key1':['a,b,c','1,2,3',[':,., ']], ... 'key2':['a-b-c','1-2-3',[':-.- ']]}) >>> print(df['key2'].str.split('-')) # Dataframe使用split 0 [a, b, c] 1 [1, 2, 3] 2 NaN Name: key2, dtype: object >>>

     字符串索引

    s.str[ 0 ]   .str[ :2 ]

    >>> 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)
    0          A
    1          b
    2          C
    3    bbhello
    4        123
    5        NaN
    6         hj
    dtype: object
    >>> print(df)
      key1  key2
    0    a   hee
    1    b    fv
    2    c     w
    3    d  hija
    4    e   123
    5    f   NaN
    >>> print(s.str[0])  # 取第一个字符串
    0      A
    1      b
    2      C
    3      b
    4      1
    5    NaN
    6      h
    dtype: object
    >>> print(s.str[:2]) # 取前两个字符串
    0      A
    1      b
    2      C
    3     bb
    4     12
    5    NaN
    6     hj
    dtype: object
    >>> print(df['key2'].str[0])  # str之后和字符串本身索引方式相同
    0      h
    1      f
    2      w
    3      h
    4      1
    5    NaN
    Name: key2, dtype: object
    >>>

    3.合并 merge、join

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

    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合并 → 类似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)
      key   A   B
    0  K0  A0  B0
    1  K1  A1  B1
    2  K2  A2  B2
    3  K3  A3  B3
    >>> print(df2)
      key   C   D
    0  K0  C0  D0
    1  K1  C1  D1
    2  K2  C2  D2
    3  K3  C3  D3
    >>>
    >>> print(pd.merge(df1, df2, on='key'))    # left:第一个df; #right:第二个df  #on:参考键; 
      key   A   B   C   D
    0  K0  A0  B0  C0  D0
    1  K1  A1  B1  C1  D1
    2  K2  A2  B2  C2  D2
    3  K3  A3  B3  C3  D3
    >>> print(df3)
      key1 key2   A   B
    0   K0   K0  A0  B0
    1   K0   K1  A1  B1
    2   K1   K0  A2  B2
    3   K2   K1  A3  B3
    >>> print(df4)
      key1 key2   C   D
    0   K0   K0  C0  D0
    1   K1   K0  C1  D1
    2   K1   K0  C2  D2
    3   K2   K0  C3  D3
    >>> print(pd.merge(df3, df4, on=['key1','key2']))  # 多个链接键,on是以什么作为参考,必须是基于一个参数的;多个键的连接-值必须是一样的
      key1 key2   A   B   C   D                        #key1=k0,key2=k0看看有没有 -->有, 再看key1=k0,key2=k1有没有 -->没有......
    0   K0   K0  A0  B0  C0  D0
    1   K1   K0  A2  B2  C1  D1
    2   K1   K0  A2  B2  C2  D2
    >>>

     >>> pd.merge(df3,df4,on=['key1']) #on以key1为参考值
      key1 key2_x A B key2_y C D
     0 K0  K0    A0 B0  K0  C0 D0  
     1 K0  K1    A1 B1  K0  C0 D0  #值可以重复
     2 K1  K0    A2 B2  K0  C1 D1
     3 K1  K0    A2 B2  K0  C2 D2
     4 K2  K1    A3 B3  K0  C3 D3

    参数how → 合并方式(how='inner'、how='outer'、how='left'、how='right')

    >>> print(pd.merge(df3,df4,on=['key1','key2'],how='inner'))  #inner:默认,取交集 ,可不写 
      key1 key2   A   B   C   D
    0   K0   K0  A0  B0  C0  D0
    1   K1   K0  A2  B2  C1  D1
    2   K1   K0  A2  B2  C2  D2
    >>> print(pd.merge(df3,df4,on=['key1','key2'],how='outer'))  # outer:取并集,全部都包含上了;数据缺失范围用NaN填充 
      key1 key2    A    B    C    D
    0   K0   K0   A0   B0   C0   D0
    1   K0   K1   A1   B1  NaN  NaN
    2   K1   K0   A2   B2   C1   D1
    3   K1   K0   A2   B2   C2   D2
    4   K2   K1   A3   B3  NaN  NaN
    5   K2   K0  NaN  NaN   C3   D3
    >>> print(pd.merge(df3,df4,on=['key1','key2'],how='left')) # left:按照df3为参考合并,数据缺失范围NaN
      key1 key2   A   B    C    D
    0   K0   K0  A0  B0   C0   D0
    1   K0   K1  A1  B1  NaN  NaN
    2   K1   K0  A2  B2   C1   D1
    3   K1   K0  A2  B2   C2   D2
    4   K2   K1  A3  B3  NaN  NaN
    >>> print(pd.merge(df3,df4,on=['key1','key2'],how='right')) # right:按照df4为参考合并,数据缺失范围NaN
      key1 key2    A    B   C   D
    0   K0   K0   A0   B0  C0  D0
    1   K1   K0   A2   B2  C1  D1
    2   K1   K0   A2   B2  C2  D2
    3   K2   K0  NaN  NaN  C3  D3
    >>>

    参数 left_on, right_on, left_index, right_index → 当键不为一个列时,可以单独设置左键与右键

    >>> df1 = pd.DataFrame({'lkey':list('bbacaab'),
    ...                    'data1':range(7)})
    >>> df2 = pd.DataFrame({'rkey':list('abd'), #lkey,rkey他们两个的名字不一样。 left_on是左边的的DataFrame用这个键,右边的DataFrame用那个键
    ...                    'date2':range(3)})   #只是个指向问题,相同就用on就可以了
    >>> print(df1)
      lkey  data1
    0    b      0
    1    b      1
    2    a      2
    3    c      3
    4    a      4
    5    a      5
    6    b      6
    >>> print(df2)
      rkey  date2
    0    a      0
    1    b      1
    2    d      2
    >>>
    >>> print(pd.merge(df1,df2,left_on='lkey',right_on='rkey')) # df1以‘lkey’为键,df2以‘rkey’为键; df1里边所有与df2相同的。
      lkey  data1 rkey  date2                                  #两个key键不一样时,一个是lkey、一个是rkey---> left_on是左边的df1用lkey作为键,righ_on是右边的df2用rkey作为键。
    0    b      0    b      1
    1    b      1    b      1
    2    b      6    b      1
    3    a      2    a      0
    4    a      4    a      0
    5    a      5    a      0
    >>> df1 = pd.DataFrame({'key':list('abcdfeg'),    # df1以‘key’为键,df2以index为键  
    ...                    'data1':range(7)})
    >>> df2 = pd.DataFrame({'date2':range(100,105)},
    ...                   index = list('abcde'))
    >>> print(df1)
      key  data1
    0   a      0
    1   b      1
    2   c      2
    3   d      3
    4   f      4
    5   e      5
    6   g      6
    >>> print(df2)
       date2
    a    100
    b    101
    c    102
    d    103
    e    104
    
    >>> print(pd.merge(df1, df2, left_on='key', right_index=True))#left_index:为True时,第一个df以index为键,默认False; right_index:为True时,第二个df以index为键,默认False
      key  data1  date2
    0   a      0    100
    1   b      1    101
    2   c      2    102
    3   d      3    103
    5   e      5    104
    >>>

    left_on, right_on, left_index, right_index可以相互组合:
    left_on + right_on, left_on + right_index, left_index + right_on, left_index + right_index

    参数 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(pd.merge(df1,df2,on='key',how='outer'))
      key  data1  date2
    0   b    1.0    2.0
    1   b    3.0    2.0
    2   b    7.0    2.0
    3   a    2.0   11.0
    4   a    5.0   11.0
    5   a    9.0   11.0
    6   c    4.0    NaN
    7   d    NaN   33.0
    >>> print(pd.merge(df1,df2,on='key',sort=True,how='outer')) # sort:按照字典顺序通过 连接键 对结果DataFrame进行排序。默认为False,设置为False会大幅提高性能
      key  data1  date2
    0   a    2.0   11.0
    1   a    5.0   11.0
    2   a    9.0   11.0
    3   b    1.0    2.0
    4   b    3.0    2.0
    5   b    7.0    2.0
    6   c    4.0    NaN
    7   d    NaN   33.0
    
    >>> x2 = pd.merge(df1,df2,on='key',sort=True,how='outer')
    
    >>> print(x2.sort_values('data1')) #sort_values('指定某列排序')   # 也可直接用Dataframe的排序方法:sort_values,sort_index
      key  data1  date2
    3   b    1.0    2.0
    0   a    2.0   11.0
    4   b    3.0    2.0
    6   c    4.0    NaN
    1   a    5.0   11.0
    5   b    7.0    2.0
    2   a    9.0   11.0
    7   d    NaN   33.0
    >>>

     >>> x2.sort_index()
       key data1 date2
     0   a   2.0  11.0
     1   a   5.0  11.0
     2   a   9.0  11.0
     3   b   1.0  2.0
     4   b   3.0  2.0
     5   b   7.0  2.0
     6   c   4.0  NaN
     7   d   NaN  33.0

     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)
         A   B
    K0  A0  B0
    K1  A1  B1
    K2  A2  B2
    >>> print(right)
         C   D
    K0  C0  D0
    K2  C2  D2
    K3  C3  D3
    >>> print(left.join(right)) #它不是how='inner',而是默认how='left'
         A   B    C    D
    K0  A0  B0   C0   D0
    K1  A1  B1  NaN  NaN
    K2  A2  B2   C2   D2
    >>> print(left.join(right,how='outer'))  # 等价于:pd.merge(left, right, left_index=True, right_index=True, how='outer')
          A    B    C    D
    K0   A0   B0   C0   D0
    K1   A1   B1  NaN  NaN
    K2   A2   B2   C2   D2
    K3  NaN  NaN   C3   D3
    >>>

    >>> 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) key data1 0 b 1 1 b 3 2 a 2 3 c 4 4 a 5 5 a 9 6 b 7 >>> print(df2) key date2 0 a 11 1 b 2 2 d 33
    >>> print(pd.merge(df1,df2,left_index=True,right_index=True,suffixes=('_1','_2'))) #为了区分两个相同的key,合并之后就给它区分了 key_1 data1 key_2 date2 #不加,就是默认为key_x , key_y 即suffixes=('_x','_y')默认哦 0 b 1 a 11 1 b 3 b 2 2 a 2 d 33 >>> print(df1.join(df2['date2'])) key data1 date2 0 b 1 11.0 1 b 3 2.0 2 a 2 33.0 3 c 4 NaN 4 a 5 NaN 5 a 9 NaN 6 b 7 NaN >>> >>> 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) A B key 0 A0 B0 K0 1 A1 B1 K1 2 A2 B2 K0 3 A3 B3 K1 >>> print(right) C D K0 C0 D0 K1 C1 D1 >>> 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 key C D #这里是left的key,不是right的;left按key,right按index。 0 A0 B0 K0 C0 D0 1 A1 B1 K1 C1 D1 2 A2 B2 K0 C0 D0 3 A3 B3 K1 C1 D1 >>>

    >>> left.join(right) 
       A B key C   D
     0 A0 B0 K0 NaN NaN
     1 A1 B1 K1 NaN NaN
     2 A2 B2 K0 NaN NaN
     3 A3 B3 K1 NaN NaN
    >>>

    4.连接与修补 concat、combine_first

    连接 - 沿轴执行连接操作

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

     连接:concat

    pd.concat([s1,s2]).sort_index() 默认axis=0     .concat([s3,s4], axis=1)
    >>> s1 = pd.Series([1,2,3])
    >>> s2 = pd.Series([2,3,4])
    >>> s3 = pd.Series([1,2,3],index = ['a','c','h'])
    >>> s4 = pd.Series([2,3,4],index = ['b','e','d'])
    >>> print(s1)
    0    1
    1    2
    2    3
    dtype: int64
    >>> print(s2)
    0    2
    1    3
    2    4
    dtype: int64
    >>> print(s3)
    a    1
    c    2
    h    3
    dtype: int64
    >>> print(s4)
    b    2
    e    3
    d    4
    dtype: int64
    >>> print(pd.concat([s1,s2])) #行与行的拼接呗
    0    1
    1    2
    2    3
    0    2
    1    3
    2    4
    dtype: int64
    >>> print(pd.concat([s3,s4]).sort_index()) # 默认axis=0,行 拼 行
    a    1
    b    2
    c    2
    d    4
    e    3
    h    3
    dtype: int64
    >>>
    
    >>> print(pd.concat([s3,s4], axis=1)) # axis=1,列+列,成为一个Dataframe
         0    1
    a  1.0  NaN
    b  NaN  2.0
    c  2.0  NaN
    d  NaN  4.0
    e  NaN  3.0
    h  3.0  NaN
    >>>

    连接方式:join,join_axes

    pd.concat([s5,s6],axis=1,join='inner')    pd.concat([s5,s6],axis=1,join_axes=[['a','b','d']])
    >>> s5 = pd.Series([1,2,3],index = ['a','b','c'])
    >>> s6 = pd.Series([2,3,4],index = ['b','c','d'])
    >>> print(s5)
    a    1
    b    2
    c    3
    dtype: int64
    >>> print(pd.concat([s5,s6],axis=1))
         0    1
    a  1.0  NaN
    b  2.0  2.0
    c  3.0  3.0
    d  NaN  4.0
    >>> print(pd.concat([s5,s6],axis=1,join='inner')) # join:{'inner','outer'},默认为“outer”并集。如何处理其他轴上的索引。  outer为联合,inner为交集。
       0  1                            #就是把NaN的值行给去掉啊,保留都有值的行
    b  2  2
    c  3  3
    >>> print(pd.concat([s5,s6],axis=1,join_axes=[['a','b','d']])) # join_axes:指定联合的index,只显示a b d轴
         0    1
    a  1.0  NaN
    b  2.0  2.0
    d  NaN  4.0

    覆盖列名

    pd.concat([s5,s6], keys = ['one','two'])    pd.concat([s5,s6], axis=1, keys = ['one','two'])
    >>> sre = pd.concat([s5,s6], keys = ['one','two'])
    >>> print(sre,type(sre))  # keys:序列,默认值无。使用传递的键作为最外层构建层次索引
    one  a    1
         b    2
         c    3
    two  b    2
         c    3
         d    4
    dtype: int64 <class 'pandas.core.series.Series'>
    >>> print(sre.index)
    MultiIndex(levels=[['one', 'two'], ['a', 'b', 'c', 'd']],
               labels=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 1, 2, 3]])
    >>> sre = pd.concat([s5,s6], axis=1, keys = ['one','two'])   # axis = 1, 覆盖列名
    >>> print(sre,type(sre))
       one  two
    a  1.0  NaN
    b  2.0  2.0
    c  3.0  3.0
    d  NaN  4.0 <class 'pandas.core.frame.DataFrame'>
    >>>

    修补 pd.combine_first()

    df1.combine_first(df2)     df1.update(df2)
    >>> 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)
         0    1    2
    0  NaN  3.0  5.0
    1 -4.6  NaN  NaN
    2  NaN  7.0  NaN
    >>> print(df2)
          0    1    2
    1 -42.6  NaN -8.2
    2  -5.0  1.6  4.0
    >>> print(df1.combine_first(df2))  # 根据index,df1的空值被df2替代; # 如果df2的index多于df1,则更新到df1上,比如index=['a',1]
         0    1    2
    0  NaN  3.0  5.0
    1 -4.6  NaN -8.2
    2 -5.0  7.0  4.0
    >>>

     >>> df1.update(df2)  # update,直接df2覆盖df1,相同index位置
     >>> print(df1)
     0 1 2
     0 NaN 3.0 5.0
     1 -42.6 NaN -8.2
     2 -5.0 1.6 4.0
     >>>

    5.去重及替换

    .duplicated / .replace

     去重 .duplicated

    s.duplicated()遇到重复的就返回True ;  s[s.duplicated() == False] 通过布尔判断去除重复的值 ;  s.drop_duplicates()  移除重复值;
    >>> s = pd.Series([1,1,1,1,2,2,2,3,4,5,5,5,5])
    >>> print(s)
    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
    >>> print(s.duplicated()) # 判断是否重复
    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
    >>> print(s[s.duplicated() == False]) # 通过布尔判断,得到不重复的值
    0    1
    4    2
    7    3
    8    4
    9    5
    dtype: int64
    >>>
    >>> s_re = s.drop_duplicates()  # drop.duplicates移除重复
    >>> print(s_re)                 # inplace参数:是否替换原值,默认False
    0    1
    4    2
    7    3
    8    4
    9    5
    dtype: int64
    >>>
    >>> df = pd.DataFrame({'key1':['a','a',3,4,5],
    ...                   'key2':['a','a','b','b','c']})
    >>> print(df.duplicated())
    0    False
    1     True
    2    False
    3    False
    4    False
    dtype: bool
    >>> print(df['key2'].duplicated())  # Dataframe中使用duplicated
    0    False
    1     True
    2    False
    3     True
    4    False
    Name: key2, dtype: bool

    替换 .replace

    s.replace('a', np.nan)   s.replace(['a','s'] ,np.nan) 可替换多个值   s.replace({'a':'hello world!','s':123}) 可传入列表或字典
    >>> s = pd.Series(list('ascaazsd'))
    >>> print(s.replace('a', np.nan))  # 可一次性替换一个值或多个值
    0    NaN
    1      s
    2      c
    3    NaN
    4    NaN
    5      z
    6      s
    7      d
    dtype: object
    >>> print(s.replace(['a','s'] ,np.nan)) 
    0    NaN
    1    NaN
    2      c
    3    NaN
    4    NaN
    5      z
    6    NaN
    7      d
    dtype: object
    >>> print(s.replace({'a':'hello world!','s':123})) # 可传入列表或字典
    0    hello world!
    1             123
    2               c
    3    hello world!
    4    hello world!
    5               z
    6             123
    7               d
    dtype: object
    >>>

    6.数据分组

    分组统计 - 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('A').mean()以A进行分组,算均值;  df.groupby(['A'])['D'].mean() 以A进行分组,算D的平均值;  
    通过分组后的计算,得到一个新的dataframe
     默认axis = 0,以行来分组,就是按数据进行分组
    可单个或多个([ ])列分组
    >>> 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)
         A      B         C         D
    0  foo    one -0.362058 -1.232524
    1  bar    one  1.038853 -1.261056
    2  foo    two  1.240874  0.120504
    3  bar  three  0.579106 -0.695712
    4  foo    two -0.107265  0.149843
    5  bar    two -0.015046 -1.024002
    6  foo    one  1.907054 -2.116334
    7  foo  three -0.826077 -0.959509
    >>>
    >>> print(df.groupby('A'),type(df.groupby('A')))   # 直接分组得到一个groupby对象,是一个中间数据,没有进行计算
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000000000B2EA748> <class 'pandas.core.groupby.groupby.DataFrameGroupBy'>
    >>>
    
    >>> a = df.groupby('A').mean()>>> print(a,type(a),'
    ',a.columns)
                C         D
    A
    bar  0.534304 -0.993590
    foo  0.370506 -0.807604 <class 'pandas.core.frame.DataFrame'>
     Index(['C', 'D'], dtype='object')

    >>> b = df.groupby(['A','B']).mean()
    >>> print(b,type(b),' ',b.columns) C D A B bar one 1.038853 -1.261056 three 0.579106 -0.695712 two -0.015046 -1.024002 foo one 0.772498 -1.674429 three -0.826077 -0.959509 two 0.566804 0.135173 <class 'pandas.core.frame.DataFrame'> Index(['C', 'D'], dtype='object')

    >>> c = df.groupby(['A'])['D'].mean() #以A分组,算D的平均值。
    >>> print(c,type(c)) A bar -0.993590 foo -0.807604 Name: D, dtype: float64 <class 'pandas.core.series.Series'> >>>

     分组 - 可迭代对象

    list(df.groupby('X'))分组后把它变成一个列表(里边嵌套元组) .[0]获取元组;
    df.groupby(['X']).get_group('B') 分组后提取出B组
    df.groupby('X').groups分组后转化为字典; df.groupby('X').groups['A']转化为字典之后提取出A组; 
    求直接得到什么组,直接用get_group;  groups查看分组后的结构哪几个序列、哪几个index组成的
    df.groupby('X').size()查看分组后的长度
    df.groupby(['A','B']).groups 按照两个列进行分组;  df.groupby(['A','B']).groups[('foo', 'three')] 
    >>> df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
    >>> print(df)
       X  Y
    0  A  1
    1  B  4
    2  A  3
    3  B  2
    >>> print(df.groupby('X'), type(df.groupby('X')))
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000000000B2D2E48> <class 'pandas.core.groupby.groupby.DataFrameGroupBy'>
    >>> print(list(df.groupby('X')), '→ 可迭代对象,直接生成list
    ')
    [('A',    X  Y  #'A'后边就是一个dataframe
    0  A  1
    2  A  3), ('B',    X  Y
    1  B  4
    3  B  2)] → 可迭代对象,直接生成list
    
    >>> print(list(df.groupby('X'))[0], '→ 以元祖形式显示
    ')
    ('A',    X  Y
    0  A  1
    2  A  3) → 以元祖形式显示
    >>>for n,g in df.groupby('X'):   # n是组名,g是分组后的Dataframe
    ...    print(n)
    ...    print('###')
    ...    print(g)
    A
       X  Y
    0  A  1
    2  A  3
    ###
    B
       X  Y
    1  B  4
    3  B  2
    
    >>> print(df.groupby(['X']).get_group('A'),'
    ')
       X  Y
    0  A  1
    2  A  3
    
    >>> print(df.groupby(['X']).get_group('B'),'
    ')   # .get_group()提取分组后的组
       X  Y
    1  B  4
    3  B  2
    
    >>> grouped = df.groupby(['X'])>>> print(grouped.groups)          # .groups:将分组后的groups转为dict 
    {'A': Int64Index([0, 2], dtype='int64'), 'B': Int64Index([1, 3], dtype='int64')}
    >>> print(grouped.groups['A'])   # 也可写:df.groupby('X').groups['A']             # 可以字典索引方法来查看groups里的元素
    Int64Index([0, 2], dtype='int64')
    >>>
    >>> sz = grouped.size()    # .size():查看分组后的长度
    >>> print(sz,type(sz))
    X
    A    2
    B    2
    dtype: int64 <class 'pandas.core.series.Series'>
    >>>
    >>> 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)})
    
    >>> df
         A      B         C         D
    0  foo    one -0.742833 -0.459537
    1  bar    one  1.584006  0.834005
    2  foo    two -0.021436  0.711519
    3  bar  three  0.104556  0.693898
    4  foo    two  0.358998  1.870570
    5  bar    two  1.626876  0.526132
    6  foo    one  0.716151 -0.414307
    7  foo  three -2.315347 -0.258841
    >>> df.groupby(['A','B']).groups   #按照两个列进行分组,转化为字典;
    {('bar', 'one'): Int64Index([1], dtype='int64'), ('bar', 'three'): Int64Index([3], dtype='int64'), ('bar', 'two'): Int64Index([5], dtype='int64'), ('foo', 'one'): Int64Index([0, 6], dtype='int64'), ('
    foo', 'three'): Int64Index([7], dtype='int64'), ('foo', 'two'): Int64Index([2, 4], dtype='int64')}
    >>> df.groupby(['A','B']).groups[('foo','three')] #查看它的结构;
    Int64Index([7], dtype='int64')
    >>> df.groupby(['A','B']).get_group(('foo','three')) #查看它的分组
         A      B         C         D
    7  foo  three -2.315347 -0.258841
    >>> df.groupby(['A','B']).get_group(('foo','one'))
         A    B         C         D
    0  foo  one -0.742833 -0.459537
    6  foo  one  0.716151 -0.414307
    >>>

    其他轴上的分组

    按数值类型去分组

    df.groupby(df.dtypes, axis=1)  df.dtypes得到的是一个Series ; 
    >>> df = pd.DataFrame({'data1':np.random.rand(2),
    ...                   'data2':np.random.rand(2),
    ...                   'key1':['a','b'],
    ...                   'key2':['one','two']})
    >>> print(df)
          data1     data2 key1 key2
    0  0.168619  0.824735    a  one
    1  0.094004  0.268596    b  two
    >>> print(df.dtypes) #会直接得到一个Series 
    data1    float64
    data2    float64
    key1      object
    key2      object
    dtype: object
    df = pd.DataFrame({'data1':np.random.rand(2),
                      'data2':np.random.rand(2),
                      'key1':['a','b'],
                      'key2':['one','two']})
    >>>for n,p in df.groupby(df.dtypes, axis=1):  # 按照值类型分列  #按照列进行分组(没有对值进行聚合),按照数值的字段类型(浮点型、字符串)
    ...    print(n)
    ...    print(p)
    ...    print('##')
    float64
          data1     data2
    0  0.204654  0.104438
    1  0.749022  0.392701
    ##
    object
      key1 key2
    0    a  one
    1    b  two
    ##

    通过字典或者Series分组

    字典的方式一般用在列上;按照行的话a,b对应的是one

    df.groupby(mapping, axis=1)  
    pd.Series(mapping)
    >>> df = pd.DataFrame(np.arange(16).reshape(4,4),
    ...                   columns = ['a','b','c','d'])
    >>> df
        a   b   c   d
    0   0   1   2   3
    1   4   5   6   7
    2   8   9  10  11
    3  12  13  14  15
    >>> mapping = {'a':'one','b':'one','c':'two','d':'two'}  #mapping字典中,a , b 列对应为one; c ,d 列对应two ;
    >>> df.groupby(mapping, axis = 1)               ##以字典来进行分组; 
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000000000299CB70>
    >>> print(df.groupby(mapping, axis=1).groups['one']) #################特别注意它的结构,a b为它的index,#############
    Index(['a', 'b'], dtype='object')
    >>> print(df.groupby(mapping,axis=1).get_group('one')) #查看它的组
        a   b
    0   0   1
    1   4   5
    2   8   9
    3  12  13
    >>> df.groupby(mapping, axis = 1).sum()  #axis=1是按照行进行计算的
       one  two
    0    1    5
    1    9   13
    2   17   21
    3   25   29
    >>>
    >>> s = pd.Series(mapping) # s中,index中a、b对应的为one,c、d对应的为two,以Series来分组
    >>> print(s,'
    ')
    a      one
    b      one
    c      two
    d      two
    dtype: object
    
    >>> print(s.groupby(s).count())
    one      2
    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,'
    ')
          a   b   c   d
    abc   0   1   2   3
    bcd   4   5   6   7
    aa    8   9  10  11
    b    12  13  14  15
    
    >>> print(df.groupby(len).sum()) # 按照index的字母长度分组;
        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])
    >>> grouped = s.groupby(level=0)  # 唯一索引用.groupby(level=0),将同一个index的分为一组
    >>> print(grouped)
    <pandas.core.groupby.groupby.SeriesGroupBy object at 0x000000000B2D2B38>
    >>> print(grouped.first(),'→ first:非NaN的第一个值
    ')
    1    1
    2    2
    3    3
    dtype: int64 → first:非NaN的第一个值
    
    >>> print(grouped.last(),'→ last:非NaN的最后一个值
    ')
    1    10
    2    20
    3    30
    dtype: int64 → last:非NaN的最后一个值
    
    >>> print(grouped.sum(),'→ sum:非NaN的和
    ')
    1    11
    2    22
    3    33
    dtype: int64 → sum:非NaN的和
    
    >>> print(grouped.mean(),'→ mean:非NaN的平均值
    ')
    1     5.5
    2    11.0
    3    16.5
    dtype: float64 → mean:非NaN的平均值
    
    >>> print(grouped.median(),'→ median:非NaN的算术中位数
    ')
    1     5.5
    2    11.0
    3    16.5
    dtype: float64 → median:非NaN的算术中位数
    
    >>> print(grouped.count(),'→ count:非NaN的值
    ')
    1    2
    2    2
    3    2
    dtype: int64 → count:非NaN的值
    
    >>> print(grouped.min(),'→ min、max:非NaN的最小值、最大值
    ')
    1    1
    2    2
    3    3
    dtype: int64 → min、max:非NaN的最小值、最大值
    
    >>> print(grouped.std(),'→ std,var:非NaN的标准差和方差
    ')
    1     6.363961
    2    12.727922
    3    19.091883
    dtype: float64 → std,var:非NaN的标准差和方差
    
    >>> print(grouped.prod(),'→ prod:非NaN的积
    ')
    1    10
    2    40
    3    90
    dtype: int64 → prod:非NaN的积
    
    >>>

    多函数计算:agg()

    df.groupby('a').agg(['mean',np.sum]) 、 df.groupby('a')['b'].agg({'result1':np.mean,'result2':np.sum}) 
    >>> 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)
       a         b         c         d
    0  1  0.296927  0.088159  0.144423
    1  1  0.658442  0.172187  0.716124
    2  2  0.978164  0.292865  0.421377
    3  2  0.288031  0.874687  0.779844
    >>> print(df.groupby('a').agg(['mean',np.sum])) #以a进行分组,想求出它的均值和sum 
              b                   c                   d
           mean       sum      mean       sum      mean       sum
    a
    1  0.477684  0.955369  0.130173  0.260346  0.430273  0.860547
    2  0.633097  1.266195  0.583776  1.167551  0.600611  1.201221
    >>> print(df.groupby('a')['b'].agg({'result1':np.mean,  #把b单独提取出来,结果以字典的形式显示。 
    ...                                'result2':np.sum}))
        result1   result2
    a
    1  0.477684  0.955369
    2  0.633097  1.266195
    >>>
    # 函数写法可以用str,或者np.方法
    # 可以通过list,dict传入,当用dict时,key名为columns

    7.分组转换及一般性“拆分-应用apply-合并”

    transform / apply

    数据分组转换,transform

    df.groupby('key2').transform(np.mean)
    >>> df = pd.DataFrame({'data1':np.random.rand(5),
    ...                   'data2':np.random.rand(5),
    ...                   'key1':list('aabba'),
    ...                   'key2':['one','two','one','two','one']})
    >>> k_mean = df.groupby('key1').mean()
    >>> print(df)
          data1     data2 key1 key2
    0  0.965986  0.086595    a  one
    1  0.981811  0.143423    a  two
    2  0.750037  0.331594    b  one
    3  0.433544  0.594493    b  two
    4  0.801283  0.022557    a  one
    >>> print(k_mean)
            data1     data2
    key1
    a     0.91636  0.084192
    b     0.59179  0.463044
    >>> print(pd.merge(df,k_mean,left_on='key1',right_index=True).add_prefix('mean_')) # .add_prefix('mean_'):添加前缀     # 通过分组、合并,得到一个包含均值的Dataframe
       mean_data1_x  mean_data2_x mean_key1 mean_key2  mean_data1_y  mean_data2_y
    0      0.965986      0.086595         a       one       0.91636      0.084192
    1      0.981811      0.143423         a       two       0.91636      0.084192
    4      0.801283      0.022557         a       one       0.91636      0.084192
    2      0.750037      0.331594         b       one       0.59179      0.463044
    3      0.433544      0.594493         b       two       0.59179      0.463044
    >>>
    >>> print(df.groupby('key2').mean())  # 按照key2分组求均值
             data1     data2
    key2
    one   0.839102  0.146916
    two   0.707678  0.368958
    >>> print(df.groupby('key2').transform(np.mean))
          data1     data2
    0  0.839102  0.146916
    1  0.707678  0.368958
    2  0.839102  0.146916
    3  0.707678  0.368958
    4  0.839102  0.146916
    >>>
     data1、data2每个位置元素取对应分组列的均值 
    # 字符串不能进行计算

    一般化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直接运行其中的函数 # 这里为匿名函数,直接描述分组后的统计量 
                   data1     data2                 # describe()就是计算统计量。 
    key1
    a    count  3.000000  3.000000
         mean   0.544703  0.643239
         std    0.423421  0.373472
         min    0.093693  0.217797
         25%    0.350207  0.506341
         50%    0.606721  0.794885
         75%    0.770208  0.855961
         max    0.933696  0.917036
    b    count  2.000000  2.000000
         mean   0.560306  0.296463
         std    0.081378  0.365345
         min    0.502763  0.038125
         25%    0.531534  0.167294
         50%    0.560306  0.296463
         75%    0.589077  0.425632
         max    0.617848  0.554801
    >>>
    def f_df1(d,n):
        return(d.sort_index()[:n]) # 参数n就是返回几个;
    def f_df2(d,k1):
        return(d[k1])
    print(df.groupby('key1').apply(f_df1,2),'
    ') #第一个参数d就是dataframe
               data1     data2 key1 key2
    key1                                
    a    0  0.913408  0.369516    a  one
         1  0.742166  0.340193    a  two
    b    2  0.975362  0.863833    b  one
         3  0.087291  0.420579    b  two 
    print(df.groupby('key1').apply(f_df2,'data2')) #按照key1分组之后按照data2做了个索引;
    key1   
    a     0    0.233298
          1    0.024352
          4    0.828523
    b     2    0.340762
          3    0.745267
    Name: data2, dtype: float64
    print(type(df.groupby('key1').apply(f_df2,'data2'))) 
    <class 'pandas.core.series.Series'>
    # f_df1函数:返回排序后的前n行数据
    # f_df2函数:返回分组后表的k1列,结果为Series,层次化索引
    # 直接运行f_df函数
    # 参数直接写在后面,也可以为.apply(f_df,n = 2))

    8.透视表及交叉表

    类似excel数据透视 - pivot table / crosstab ;groupby是按照逻辑,pivot table透视表是按照功能

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

    pd.pivot_table(df, values = 'values', index = 'date', columns = 'key', aggfunc=np.sum)
    >>> 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)
            date key    values
    0 2017-05-01   a  9.990137
    1 2017-05-02   b  0.888088
    2 2017-05-03   c  9.568805
    3 2017-05-01   d  3.617859
    4 2017-05-02   a  6.341511
    5 2017-05-03   b  5.447269
    6 2017-05-01   c  7.827543
    7 2017-05-02   d  9.753436
    8 2017-05-03   a  6.048343
    >>> print(pd.pivot_table(df, values = 'values', index = 'date', columns = 'key', aggfunc=np.sum))  # 也可以写 aggfunc='sum'
    key                a         b         c         d
    date
    2017-05-01  9.990137       NaN  7.827543  3.617859
    2017-05-02  6.341511  0.888088       NaN  9.753436
    2017-05-03  6.048343  5.447269  9.568805       NaN
    >>> # data:DataFrame对象
    ... # values:要聚合的列或列的列表。  就是df里边的数据,分组的结果聚合哪些数据;
    ... # index:是做完数据透视表之后的index,从原数据的列中筛选。  要以哪个值作为参考,数据透视表后的那个index就是分组的那个index,拿哪个字段作为分组;
    ... # columns:数据透视表的columns,从原数据的列中筛选 
    ... # aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
    ...
    >>> print(pd.pivot_table(df, values = 'values', index = ['date','key'], aggfunc=len))
                    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
    >>> # 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
    ... # aggfunc=len(或者count):计数

    交叉表: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)
       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
    >>> print(pd.crosstab(df['A'],df['B'])) # 如果crosstab只接收两个Series,它将提供一个频率表。  #用A的唯一值,统计B唯一值的出现次数
    B  3  4            #当A值为1,B值为3时,有1个; A为2,B为3时有1个; A为2,B为4时有3个。
    A                      
    1  1  0
    2  1  3 
    >>> print(pd.crosstab(df['A'],df['B'],normalize=True)) # normalize:默认False,将所有值除以值的总和进行归一化 → 为True时候显示百分比
    B    3    4         #就是说当A为1,B为3时,有1个,1/(1+1+0+3)=0.2 这样一个百分比。
    A
    1  0.2  0.0
    2  0.2  0.6
    >>> print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum)) # values:可选,根据因子聚合的值数组 # aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算  # 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
    B    3    4         #就是说当A=1,B=3时,求C列的和为1 
    A
    1  1.0  NaN 
    2  1.0  2.0
    >>> print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum, margins=True)) # margins:布尔值,默认值False,给你加个行/列边距(小计),为了好看点
    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
    >>>

    9.数据读取

    核心:read_tableread_csv,  read_excel 

    C:UsersAdministrator>pip install xlrd
    Collecting xlrd #先安装下这个模块
      Downloading https://files.pythonhosted.org/packages/07/e6/e95c4eec6221bfd8528bcc4ea252a850bf
        100% |████████████████████████████████| 112kB 171kB/s
    Installing collected packages: xlrd
    Successfully installed xlrd-1.1.0

    读取普通分隔数据:read_table,可以读取txt,csv

    import os
    os.chdir(r'C:UsersAdministratorDesktop')
    
    data1 = pd.read_table('data1.txt', delimiter=',',header = 0, index_col=1) # delimiter:用于拆分的字符,也可以用sep:sep = ','#header:用做列名的序号,默认为0(第一行) # index_col:指定某列为行索引,否则自动索引0, 1, .....
    print(data1)                                   header=0就是把首行第一行作为columns  #index_col=0就是把第一列当做索引,不写它或None就是默认的自动添加;     
         va1  va3  va4
    va2               
    2      1    3    4
    3      2    4    5
    4      3    5    6
    5      4    6    7
    读取csv数据:read_csv                                
    # 先熟悉一下excel怎么导出csv
    data2 = pd.read_csv('地市级党委书记数据库(2000-10).csv',engine = 'python',encoding='utf-8') # engine:使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
    # encoding:指定字符集类型,即编码,通常指定为'utf-8'
    # 大多数情况先将excel导出csv,再读取
    print(data2.head()) # read_table主要用于读取简单的数据,txt/csv
     省级政区代码 省级政区名称  地市级政区代码 地市级政区名称    年份 ...  专业:理工  专业:农科  专业:医科  入党年份 工作年份
    0  130000    河北省   130100    石家庄市  2000 ...    NaN    NaN    NaN   NaN  NaN
    1  130000    河北省   130100    石家庄市  2001 ...    1.0    0.0    0.0   NaN  NaN
    2  130000    河北省   130100    石家庄市  2002 ...    1.0    0.0    0.0   NaN  NaN
    3  130000    河北省   130100    石家庄市  2003 ...    1.0    0.0    0.0   NaN  NaN
    4  130000    河北省   130100    石家庄市  2004 ...    1.0    0.0    0.0   NaN  NaN
    
    [5 rows x 23 columns]
    
    读取excel数据:read_excel                           
    data3 = pd.read_excel('地市级党委书记数据库(2000-10).xlsx',sheetname='中国人民共和国地市级党委书记数据库(2000-10)',header=0)
    # io :文件路径。                        sheetname就是你的excel文件里边可能有多个文件,你可以写文件名也可以写 0就是第一个文件,1第二个文件;None是给你读取成个字典,把excel里边两个表都读出来;list就是 [0,1] 
    # sheetname:返回多表使用sheetname=[0,1],若sheetname=None是返回全表 → ① int/string 返回的是dataframe ②而none和list返回的是dict
    # header:指定列名行,默认0,即取第一行
    # index_col:指定列为索引列,也可以使用u”strings”
    print(data3)
          省级政区代码    省级政区名称  地市级政区代码   地市级政区名称  ...   专业:农科 专业:医科  入党年份  工作年份
    0     130000       河北省   130100      石家庄市  ...     NaN   NaN   NaN   NaN
    1     130000       河北省   130100      石家庄市  ...     0.0   0.0   NaN   NaN
    2     130000       河北省   130100      石家庄市  ...     0.0   0.0   NaN   NaN
    3     130000       河北省   130100      石家庄市  ...     0.0   0.0   NaN   NaN
    4     130000       河北省   130100      石家庄市  ...     0.0   0.0   NaN   NaN
    5     130000       河北省   130100      石家庄市  ...     0.0   0.0   NaN   NaN
    ...
    3661  650000  新疆维吾尔自治区   654300     阿勒泰地区  ...     NaN   NaN   NaN   NaN
    3662  650000  新疆维吾尔自治区   654300     阿勒泰地区  ...     NaN   NaN   NaN   NaN
    
    [3663 rows x 23 columns]
  • 相关阅读:
    071:【Django数据库】ORM聚合函数详解-Avg
    实战:百度知道营销,自问自答技巧(下)
    实战:百度知道营销,自问自答技巧(上)
    QQ群排名霸屏技术居然是这样简单
    百度云盘,资源引流的温床,你绝对值得拥有!
    PC时代 常用搜索引擎高级指令 勿忘
    免费影视资源 日引不说几百上千 反正绝对不会是零
    QQ兴趣部落 大批量引流实战技巧
    新媒体运营之话说如此操作更容易出站街号。
    QQ群认证 人数再度扩容 权限随之升级
  • 原文地址:https://www.cnblogs.com/shengyang17/p/9527386.html
Copyright © 2011-2022 走看看