Fork me on GitHub

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值的数量\n')
key1    10
key2    10
dtype: int64 → count统计非Na值的数量

>>> print(df.min(),'→ min统计最小值\n',df['key2'].max(),'→ max统计最大值\n')
key1    0.000000
key2    0.275988
dtype: float64 → min统计最小值
 8.650397903041455 → max统计最大值

>>> print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置\n') #q=0.75,分位数就是总共数的3/4位置的那个数
key1    6.750000
key2    6.611727
Name: 0.75, dtype: float64 → quantile统计分位数,参数q确定位置

>>> print(df.sum(),'→ sum求和\n')
key1    45.000000
key2    43.658172
dtype: float64 → sum求和

>>> print(df.mean(),'→ mean求平均值\n')
key1    4.500000
key2    4.365817
dtype: float64 → mean求平均值

>>> print(df.median(),'→ median求算数中位数,50%分位数\n')
key1    4.500000
key2    4.165668
dtype: float64 → median求算数中位数,50%分位数

>>> print(df.std(),'\n',df.var(),'→ std,var分别求标准差,方差\n')
key1    3.027650
key2    2.800485
dtype: float64
 key1    9.166667
key2    7.842718
dtype: float64 → std,var分别求标准差,方差

>>> print(df.skew(),'→ skew样本的偏度\n')  #偏度和峰度是用来进行一致性检验的。
key1    0.000000
key2    0.094214
dtype: float64 → skew样本的偏度

>>> print(df.kurt(),'→ kurt样本的峰度\n')
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样本的累计和\n')
    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样本的累计积\n')
    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(),'\n',df.cummin(),'→ cummax,cummin分别求累计最大值,累计最小值\n') #累计最大值和最小值会直接填充之前的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小写\n') 0 a 1 b 2 bbhello 3 123 4 NaN dtype: object → lower小写 >>> print(s.str.upper(),'→ lower大写\n') 0 A 1 B 2 BBHELLO 3 123 4 NaN dtype: object → lower大写 >>> print(s.str.len(),'→ len字符长度\n') 0 1.0 1 1.0 2 7.0 3 3.0 4 NaN dtype: float64 → len字符长度 >>> print(s.str.startswith('b'),'→ 判断起始是否为a\n') 0 False 1 True 2 True 3 False 4 NaN dtype: object → 判断起始是否为a >>> print(s.str.endswith('3'),'→ 判断结束是否为3\n') 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  排序 | 

Series 的排序: Series.sort_values(ascending=True, inplace=False) 参数说明:

  • ascending:默认为True升序排序,为False降序排序
  • inplace:是否修改原始Series

DataFrame 的排序: DataFrame.sort_values(by, ascending=True, inplace=False) 参数说明:

  • by:字符串或者List<字符串>,单列排序或者多列排序
  • ascending:bool或者List,升序还是降序,如果是list对应by的多列
  • inplace:是否修改原始DataFrame 
>>> 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),'\n',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),'\n',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\n')
[('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], '→ 以元祖形式显示\n')
('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'),'\n')
   X  Y
0  A  1
2  A  3

>>> print(df.groupby(['X']).get_group('B'),'\n')   # .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,'\n')
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,'\n')
      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的第一个值\n')
1    1
2    2
3    3
dtype: int64 → first:非NaN的第一个值

>>> print(grouped.last(),'→ last:非NaN的最后一个值\n')
1    10
2    20
3    30
dtype: int64 → last:非NaN的最后一个值

>>> print(grouped.sum(),'→ sum:非NaN的和\n')
1    11
2    22
3    33
dtype: int64 → sum:非NaN的和

>>> print(grouped.mean(),'→ mean:非NaN的平均值\n')
1     5.5
2    11.0
3    16.5
dtype: float64 → mean:非NaN的平均值

>>> print(grouped.median(),'→ median:非NaN的算术中位数\n')
1     5.5
2    11.0
3    16.5
dtype: float64 → median:非NaN的算术中位数

>>> print(grouped.count(),'→ count:非NaN的值\n')
1    2
2    2
3    2
dtype: int64 → count:非NaN的值

>>> print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
1    1
2    2
3    3
dtype: int64 → min、max:非NaN的最小值、最大值

>>> print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
1     6.363961
2    12.727922
3    19.091883
dtype: float64 → std,var:非NaN的标准差和方差

>>> print(grouped.prod(),'→ prod:非NaN的积\n')
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),'\n') #第一个参数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:\Users\Administrator>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:\Users\Administrator\Desktop')

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]

 

 
posted @ 2018-08-27 21:18  kris12  阅读(3090)  评论(0编辑  收藏  举报
levels of contents