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 7.556713
1 1 8.650398 16.207111
2 2 4.692490 20.899601
3 3 0.275988 21.175589
4 4 2.710686 10 23.886275
5 5 5.130423 29.016698
6 6 3.638846 32.655544
7 7 2.989476 35.645019
8 8 7.105496 42.750515
9 9 0.907657 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','',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','',np.nan,'hj'])
>>> df = pd.DataFrame({'key1':list('abcdef'),
... 'key2':['hee','fv','w','hija','',np.nan]})
>>> print(s)
A
b
C
bbhello NaN
hj
dtype: object
>>> print(df)
key1 key2
a hee
b fv
c w
d hija
e
f NaN
>>>
>>> print(s.str.count('b')) # 直接通过.str调用字符串方法 # 可以对Series、Dataframe使用 # 自动过滤NaN值
0.0
1.0
0.0
2.0
0.0
NaN
0.0
dtype: float64
>>> print(df['key2'].str.upper())
HEE
FV
W
HIJA NaN
Name: key2, dtype: object
>>>
>>> df.columns = df.columns.str.upper() # df.columns是一个Index对象,也可使用.str
>>> print(df)
KEY1 KEY2
a hee
b fv
c w
d hija
e
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','',np.nan,'hj'])
>>> df = pd.DataFrame({'key1':list('abcdef'),
... 'key2':['hee','fv','w','hija','',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','',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\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','',np.nan,'hj'])
>>> df = pd.DataFrame({'key1':list('abcdef'),
... 'key2':['hee','fv','w','hija','',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),'\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_table, read_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]