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 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]
04. Pandas 3| 数值计算与统计、合并连接去重分组透视表文件读取的更多相关文章
- pandas之数值计算与统计
数值计算与统计 对于DataFrame来说,求和.最大.最小.平均等统计方法,默认是按列进行统计,即axis = 0,如果添加参数axis = 1则会按照行进行统计. 如果存在空值,在统计时默认会忽略 ...
- pandas常用操作详解(复制别人的)——数据透视表操作:pivot_table()
原文链接:https://www.cnblogs.com/Yanjy-OnlyOne/p/11195621.html 一文看懂pandas的透视表pivot_table 一.概述 1.1 什么是透视表 ...
- oracle 表连接 - sort merge joins 排序合并连接
https://blog.csdn.net/dataminer_2007/article/details/41907581一. sort merge joins连接(排序合并连接) 原理 指的是两个表 ...
- SQL连接操作符介绍(循环嵌套, 哈希匹配和合并连接)
今天我将介绍在SQLServer 中的三种连接操作符类型,分别是:循环嵌套.哈希匹配和合并连接.主要对这三种连接的不同.复杂度用范例的形式一一介绍. 本文中使用了示例数据库AdventureWorks ...
- 升级Ubuntu 16.04 LTS后 DSL拨号上网(ppp)连接自动断开解决办法
原本在Ubuntu 15.10用拨号上网没有问题,但升级了16.04 LTS后发现原来的DSL连接不上了.主要表现为: 1.在NetworkManager里面选择DSL Connection能够尝试拨 ...
- 排序合并连接(sort merge join)的原理
排序合并连接(sort merge join)的原理 排序合并连接(sort merge join)的原理 排序合并连接(sort merge join) 访问次数:两张表都只会访 ...
- Oracle 多行记录合并/连接/聚合字符串的几种方法
怎么合并多行记录的字符串,一直是oracle新手喜欢问的SQL问题之一,关于这个问题的帖子我看过不下30个了,现在就对这个问题,进行一个总结.-什么是合并多行字符串(连接字符串)呢,例如: SQL&g ...
- oracle表连接------>排序合并连接(Merge Sort Join)
排序合并连接 (Sort Merge Join)是一种两个表在做连接时用排序操作(Sort)和合并操作(Merge)来得到连接结果集的连接方法. 对于排序合并连接的优缺点及适用场景例如以下: a,通常 ...
- pandas学习(常用数学统计方法总结、读取或保存数据、缺省值和异常值处理)
pandas学习(常用数学统计方法总结.读取或保存数据.缺省值和异常值处理) 目录 常用数学统计方法总结 读取或保存数据 缺省值和异常值处理 常用数学统计方法总结 count 计算非NA值的数量 de ...
随机推荐
- linux计算服务器最近一次重启的时间
date -d "$(awk -F. '{print $1}' /proc/uptime) second ago" +"%Y-%m-%d %H:%M:%S" 这 ...
- 神经网络之 Batch Normalization
知乎 csdn Batch Normalization 学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/50866313 作者:hjimce ...
- java子类对象和成员变量的隐写&方法重写
1.子类继承的方法只能操作子类继承和隐藏的成员变量名字类新定义的方法可以操作子类继承和子类新生命的成员变量,但是无法操作子类隐藏的成员变量(需要适用super关键字操作子类隐藏的成员变量.) publ ...
- 第四周学习总结-HTML
2018年8月5日 这是暑假第四周,这一周我在菜鸟教程网学到了许多HTML的知识.HTML编写网页不像C语言.Java语言那必须有主方法.主函数什么的,它基本上都是标签(元素),但是它可以与CSS(层 ...
- python发送邮件(在邮件中显示HTMLTestRunner生成的报告)
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart f ...
- Android SQLite用法
1.创建SQLite数据库 需要自己创建一个类来继承SQLiteOpenHelper类 SQLiteOpenHelper类是一个创建SQLite数据库的辅助类 继承此类的时候需要重写三个方法 publ ...
- 学习REST
REST:Representational State Transfer,资源的表现状态转换.可以理解为对资源的操作. 1. 资源 资源就是业务对象,如图片.文本.歌曲或者客户.交易等.这些是用户 ...
- 步步为营-78-新闻展示(Ajax+Json+easyUI)
Json:JavaScript Object Notation 1.1 Json对象的接收处理 <!DOCTYPE html> <html xmlns="http://ww ...
- HDU 2588 GCD(欧拉函数)
GCD Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- mac下安装Brew 警告:Warning: /usr/local/bin is not in your PATH.
终端输入命令 export PATH=/usr/local/bin:$PATH