Pandas的使用技巧相关知识点总结
pandas的使用技巧相关知识点总结表.png
一、数学计算与统计基础
(1)基本参数axis和skipna
# 基本参数:axis、skipna
# 创建dataframe
df = pd.DataFrame({'key1':[4,5,3,np.nan,2],
'key2':[1,2,np.nan,4,5],
'key3':[1,2,3,'j','k']},
index = ['a','b','c','d','e'])
print(df)
print(df['key1'],df['key1'].dtype)
print(df['key2'],df['key2'].dtype)
print(df['key3'],df['key3'].dtype)
print('---------------------')
data = df.mean()
print(data)
# .mean()计算均值,只统计元素是数字的列
# 按列计算每列的平均值,因key3含有字符串,返回只有key1和key2
# 单独统计一列,就索引要统计那列即可
# 单独统计key2这列
data2 = df['key2'].mean()
print(data2)
print('---------------------')
# 参数axis,默认为0,按列来计算
# 参数axis=1,则按行来计算
data3 = df.mean(axis=1)
print(data3)
print('---------------------')
# 从返回的data3结果来看,因原数据dataframe中含Nan,默认自动忽略Nan
# 参数skipna就是定义是否忽略Nan
# 参数skipna默认为True → 忽略Nan
# 参数skipna为False → 不忽略Nan,有Nan的列统计结果仍为Nan
data4 = df.mean(skipna=False)
data5 = df.mean(axis=1,skipna=False)
print(data4)
print(data5)
输出结果:
key1 key2 key3
a 4.0 1.0 1
b 5.0 2.0 2
c 3.0 NaN 3
d NaN 4.0 j
e 2.0 5.0 k
a 4.0
b 5.0
c 3.0
d NaN
e 2.0
Name: key1, dtype: float64 float64
a 1.0
b 2.0
c NaN
d 4.0
e 5.0
Name: key2, dtype: float64 float64
a 1
b 2
c 3
d j
e k
Name: key3, dtype: object object
---------------------
key1 3.5
key2 3.0
dtype: float64
3.0
---------------------
a 2.5
b 3.5
c 3.0
d 4.0
e 3.5
dtype: float64
---------------------
key1 NaN
key2 NaN
dtype: float64
a 2.5
b 3.5
c NaN
d NaN
e 3.5
dtype: float64
(2)主要数学计算方法
--->>> 数学计算方法①
# 主要数学计算方法①
# 可用于Series和DataFrame
df = pd.DataFrame({'key1':np.arange(10),
'key2':np.random.rand(10)*10})
print(df)
print('-----------------')
print(df.count(),'→ count统计非Na值的数量\n')
print(df.min(),'→ min统计最小值\n',df['key2'].max(),'→ max统计最大值\n')
print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置\n')
print(df.sum(),'→ sum求和\n')
print(df.mean(),'→ mean求平均值\n')
print(df.median(),'→ median求算数中位数,50%分位数\n')
print(df.std(),'\n',df.var(),'→ std,var分别求标准差,方差\n')
print(df.skew(),'→ skew样本的偏度\n')
print(df.kurt(),'→ kurt样本的峰度\n')
输出结果:
key1 key2
0 0 4.253328
1 1 0.960379
2 2 3.511730
3 3 2.509393
4 4 0.054089
5 5 8.111823
6 6 4.844677
7 7 3.198498
8 8 3.034000
9 9 3.702352
-----------------
key1 10
key2 10
dtype: int64 → count统计非Na值的数量
key1 0.000000
key2 0.054089
dtype: float64 → min统计最小值
8.111822673021239 → max统计最大值
key1 6.750000
key2 4.115584
Name: 0.75, dtype: float64 → quantile统计分位数,参数q确定位置
key1 45.000000
key2 34.180269
dtype: float64 → sum求和
key1 4.500000
key2 3.418027
dtype: float64 → mean求平均值
key1 4.500000
key2 3.355114
dtype: float64 → median求算数中位数,50%分位数
key1 3.027650
key2 2.191696
dtype: float64
key1 9.166667
key2 4.803533
dtype: float64 → std,var分别求标准差,方差
key1 0.000000
key2 0.701767
dtype: float64 → skew样本的偏度
key1 -1.200000
key2 1.858886
dtype: float64 → kurt样本的峰度
--->>> 数学计算方法②
# 主要数学计算方法②
# 可用于Series和DataFrame(2)
df = pd.DataFrame({'key1':np.arange(10),
'key2':np.random.rand(10)*10})
print(df)
print('-----------------')
# .cumsum()计算累计和
df['key1_s'] = df['key1'].cumsum()
df['key2_s'] = df['key2'].cumsum()
print(df,'→ cumsum样本的累计和\n')
print('-----------------')
# .cumprod()计算累计积
df['key1_p'] = df['key1'].cumprod()
df['key2_p'] = df['key2'].cumprod()
print(df,'→ cumprod样本的累计积\n')
print('-----------------')
# .cummax()求累计最大值,就是指累计的过程中要累计的数据中最大的值,就会一直被填充
# .cummin()求累计最小值,就是指累计的过程中要列举的数据中最小的值,就会一直被填充
print(df.cummax(),'\n',df.cummin(),'→ cummax,cummin分别求累计最大值,累计最小值\n')
# 会填充key1,和key2的值
输出结果:
key1 key2
0 0 6.782298
1 1 8.826684
2 2 5.330644
3 3 1.284093
4 4 2.040580
5 5 5.194812
6 6 4.981178
7 7 3.467392
8 8 6.802496
9 9 1.212725
-----------------
key1 key2 key1_s key2_s
0 0 6.782298 0 6.782298
1 1 8.826684 1 15.608982
2 2 5.330644 3 20.939626
3 3 1.284093 6 22.223719
4 4 2.040580 10 24.264299
5 5 5.194812 15 29.459111
6 6 4.981178 21 34.440289
7 7 3.467392 28 37.907680
8 8 6.802496 36 44.710176
9 9 1.212725 45 45.922902 → cumsum样本的累计和
-----------------
key1 key2 key1_s key2_s key1_p key2_p
0 0 6.782298 0 6.782298 0 6.782298
1 1 8.826684 1 15.608982 0 59.865201
2 2 5.330644 3 20.939626 0 319.120053
3 3 1.284093 6 22.223719 0 409.779981
4 4 2.040580 10 24.264299 0 836.188665
5 5 5.194812 15 29.459111 0 4343.843239
6 6 4.981178 21 34.440289 0 21637.455452
7 7 3.467392 28 37.907680 0 75025.529833
8 8 6.802496 36 44.710176 0 510360.865310
9 9 1.212725 45 45.922902 0 618927.582201 → cumprod样本的累计积
-----------------
key1 key2 key1_s key2_s key1_p key2_p
0 0.0 6.782298 0.0 6.782298 0.0 6.782298
1 1.0 8.826684 1.0 15.608982 0.0 59.865201
2 2.0 8.826684 3.0 20.939626 0.0 319.120053
3 3.0 8.826684 6.0 22.223719 0.0 409.779981
4 4.0 8.826684 10.0 24.264299 0.0 836.188665
5 5.0 8.826684 15.0 29.459111 0.0 4343.843239
6 6.0 8.826684 21.0 34.440289 0.0 21637.455452
7 7.0 8.826684 28.0 37.907680 0.0 75025.529833
8 8.0 8.826684 36.0 44.710176 0.0 510360.865310
9 9.0 8.826684 45.0 45.922902 0.0 618927.582201
key1 key2 key1_s key2_s key1_p key2_p
0 0.0 6.782298 0.0 6.782298 0.0 6.782298
1 0.0 6.782298 0.0 6.782298 0.0 6.782298
2 0.0 5.330644 0.0 6.782298 0.0 6.782298
3 0.0 1.284093 0.0 6.782298 0.0 6.782298
4 0.0 1.284093 0.0 6.782298 0.0 6.782298
5 0.0 1.284093 0.0 6.782298 0.0 6.782298
6 0.0 1.284093 0.0 6.782298 0.0 6.782298
7 0.0 1.284093 0.0 6.782298 0.0 6.782298
8 0.0 1.284093 0.0 6.782298 0.0 6.782298
9 0.0 1.212725 0.0 6.782298 0.0 6.782298 → cummax,cummin分别求累计最大值,累计最小
(3)唯一值判断.unique()
# 唯一值:.unique()
# 创建Series
s = pd.Series(list('asdvasdcfgg'))
print(s)
print('---------------')
# sq是只有为唯一值的Seires
sq = s.unique()
print(sq,type(sq))
# 将唯一值转变为Series
# 得到一个唯一值数组
# 通过pd.Series重新变成新的Series
s2 = pd.Series(sq)
print(s2)
sq.sort()
print(sq)
# 重新排序
输出结果:
0 a
1 s
2 d
3 v
4 a
5 s
6 d
7 c
8 f
9 g
10 g
dtype: object
---------------
['a' 's' 'd' 'v' 'c' 'f' 'g']
0 a
1 s
2 d
3 v
4 c
5 f
6 g
dtype: object
['a' 'c' 'd' 'f' 'g' 's' 'v']
(4)值values的计数.value_counts()
# 值计数:.value_counts()
s = pd.Series(list('asdvasdcfgg'))
print(s)
print('-----------------')
# 对s的values进行计数(次数)
sc = s.value_counts()
print(sc)
sc2 = s.value_counts(sort=False)
print(sc2)
# 得到一个新的Series,计算出不同值出现的频率
# sort参数:排序,默认为True
print('-----------------')
print(s)
输出结果:
0 a
1 s
2 d
3 v
4 a
5 s
6 d
7 c
8 f
9 g
10 g
dtype: object
-----------------
a 2
s 2
g 2
d 2
f 1
c 1
v 1
dtype: int64
v 1
d 2
g 2
c 1
f 1
s 2
a 2
dtype: int64
-----------------
0 a
1 s
2 d
3 v
4 a
5 s
6 d
7 c
8 f
9 g
10 g
dtype: object
(5)成员资格判断.isin()
# 成员资格:.isin()
s = pd.Series(np.arange(10,15))
df = pd.DataFrame({'key1':list('asdcbvasd'),
'key2':np.arange(4,13)})
print(s)
print(df)
print('-----')
print(s.isin([5,14])) # 判断5或14是否在s里
print(df.isin(['a','bc','10',8]))
# 用[]表示
# 得到一个布尔值的Series或者Dataframe
输出结果:
0 10
1 11
2 12
3 13
4 14
dtype: int32
key1 key2
0 a 4
1 s 5
2 d 6
3 c 7
4 b 8
5 v 9
6 a 10
7 s 11
8 d 12
-----
0 False
1 False
2 False
3 False
4 True
dtype: bool
key1 key2
0 True False
1 False False
2 False False
3 False False
4 False True
5 False False
6 True False
7 False False
8 False False
二、文本数据的常用操作
Pandas针对字符串配备了一套方法,使其易于对数组的每个元素进行操作。
(1)通过str访问文本数据
# 通过str访问文本数据并且自动排除丢失/Nan值
# 创建Series和Dataframe
s = pd.Series(['A','b','C','bbhello','123',np.nan,'hj'])
df = pd.DataFrame({'key1':list('abcdef'),
'key2':['hee','fv','w','hija','123',np.nan]})
print(s)
print('------')
print(df)
print('----------------')
# 通过str访问Series和Dataframe类型的文本数据
# str访问会自动过滤Nan值
print(s.str.count('b')) # 对s里面的每次个数据的b元素进行计数
print(df['key2'].str.upper()) # 将df里面的key2列的元素变为大写
# 对columns用str访问,因为df.columns是一个Index对象,也可使用.str
df.columns = df.columns.str.upper()
print(df)
输出结果:
0 A
1 b
2 C
3 bbhello
4 123
5 NaN
6 hj
dtype: object
------
key1 key2
0 a hee
1 b fv
2 c w
3 d hija
4 e 123
5 f NaN
----------------
0 0.0
1 1.0
2 0.0
3 2.0
4 0.0
5 NaN
6 0.0
dtype: float64
0 HEE
1 FV
2 W
3 HIJA
4 123
5 NaN
Name: key2, dtype: object
KEY1 KEY2
0 a hee
1 b fv
2 c w
3 d hija
4 e 123
5 f NaN
(2)字符串常用方法
其实就是str不可变序列里面的针对字符串的方法,都可以通过str对pandas的文本数据进行操作。
--->>>字符串常用方法①
# 字符串常用方法①- lower,upper,len,startswith,endswith
s = pd.Series(['A','b','bbhello','123',np.nan])
print(s)
print('----------------')
# 将文本数据的字符串字母变小写
print(s.str.lower(),'→ lower小写\n')
# 将文本数据的字符串字母变大写
print(s.str.upper(),'→ upper大写\n')
# 计数每行数据的字符串长度
print(s.str.len(),'→ len字符长度\n')
print(s.str.startswith('b'),'→ 判断起始是否为a\n')
print(s.str.endswith('3'),'→ 判断结束是否为3\n')
输出结果:
0 A
1 b
2 bbhello
3 123
4 NaN
dtype: object
----------------
0 a
1 b
2 bbhello
3 123
4 NaN
dtype: object → lower小写
0 A
1 B
2 BBHELLO
3 123
4 NaN
dtype: object → upper大写
0 1.0
1 1.0
2 7.0
3 3.0
4 NaN
dtype: float64 → len字符长度
0 False
1 True
2 True
3 False
4 NaN
dtype: object → 判断起始是否为a
0 False
1 False
2 False
3 True
4 NaN
dtype: object → 判断结束是否为3
--->>>字符串常用方法②
# 字符串常用方法② - strip
# 创建Series和Dataframe
s = pd.Series([' jack', 'jill ', ' jesse ', 'frank'])
df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
index=range(3))
print(s)
print(df)
print('-------------')
print(s.str.strip()) # 去除字符串中的空格
print(s.str.lstrip()) # 去除字符串中的左空格
print(s.str.rstrip()) # 去除字符串中的右空格
#df.columns = df.columns.str.strip()
#print(df)
# 这里去掉了columns的前后空格,但没有去掉中间空格
# 那就可以用replace将中间空格替换为其他
输出结果:
0 jack
1 jill
2 jesse
3 frank
dtype: object
Column A Column B
0 -0.680736 0.817757
1 -1.037254 -1.264084
2 0.424927 -1.150749
-------------
0 jack
1 jill
2 jesse
3 frank
dtype: object
0 jack
1 jill
2 jesse
3 frank
dtype: object
0 jack
1 jill
2 jesse
3 frank
dtype: object
--->>>字符串常用方法③
# 字符串常用方法(3) - replace
df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
index=range(3))
print(df)
df.columns = df.columns.str.replace(' ','-')
print(df)
# 用.replace替换,将中间的空格用“-”替换
df.columns = df.columns.str.replace('-','hehe',n=1)
print(df)
# “-”用hehe来替换,且只替换一个“-”
# 参数n=1,表示替换个数为1个
输出结果:
Column A Column B
0 0.143967 -0.426351
1 -1.210151 0.320342
2 -0.825522 -1.299585
-Column-A- -Column-B-
0 0.143967 -0.426351
1 -1.210151 0.320342
2 -0.825522 -1.299585
heheColumn-A- heheColumn-B-
0 0.143967 -0.426351
1 -1.210151 0.320342
2 -0.825522 -1.299585
--->>>字符串常用方法④【重点掌握知识!】
# 字符串常用方法④ - split、rsplit
s = pd.Series(['a,b,c','1,2,3',['a,,,c'],np.nan])
print(s)
print(s.str.split(',')) # 根据逗号进行拆分
print('-----')
# 类似字符串的split
# 返回的数据里,因为split只用于字符串不用于列表,所以['a,,,c']返回Nan
print(s.str.split(',')[0]) # 选取拆分后的第一行
print('-----')
# 直接索引得到一个list
print(s.str.split(',').str[0]) # 选择第一个元素
print(s.str.split(',').str.get(1)) # 选择第二个元素
print('-----')
# 可以使用get或[]符号访问拆分列表中的元素
print(s.str.split(',', expand=True)) # 分割拓展全部
print(s.str.split(',', expand=True, n = 1))
print(s.str.rsplit(',', expand=True, n = 1))
print('-----')
# 参数expand可以轻松扩展此操作以返回DataFrame
# expand参数,默认为False,expand=True可以分割拓展全部
# n参数限制分割数,n=1,分割数为1,只分隔1列,其他列还是连在一起
# rsplit类似于split,反向工作,即从字符串的末尾到字符串的开头
# 对Dataframe进行split操作
df = pd.DataFrame({'key1':['a,b,c','1,2,3',[':,., ']],
'key2':['a-b-c','1-2-3',[':-.- ']]})
print(df)
print(df['key2'].str.split('-'))
# Dataframe使用split
输出结果:
0 a,b,c
1 1,2,3
2 [a,,,c]
3 NaN
dtype: object
0 [a, b, c]
1 [1, 2, 3]
2 NaN
3 NaN
dtype: object
-----
['a', 'b', 'c']
-----
0 a
1 1
2 NaN
3 NaN
dtype: object
0 b
1 2
2 NaN
3 NaN
dtype: object
-----
0 1 2
0 a b c
1 1 2 3
2 NaN NaN NaN
3 NaN NaN NaN
0 1
0 a b,c
1 1 2,3
2 NaN NaN
3 NaN NaN
0 1
0 a,b c
1 1,2 3
2 NaN NaN
3 NaN NaN
-----
key1 key2
0 a,b,c a-b-c
1 1,2,3 1-2-3
2 [:,., ] [:-.- ]
0 [a, b, c]
1 [1, 2, 3]
2 NaN
Name: key2, dtype: object
(3)字符串索引
# 字符串索引
s = pd.Series(['A','b','C','bbhello','123',np.nan,'hj'])
df = pd.DataFrame({'key1':list('abcdef'),
'key2':['hee','fv','w','hija','123',np.nan]})
print(s)
print(df)
print('-----------------------------')
print(s.str[0]) # 取第一个字符串
print(s.str[:2]) # 取前两个字符串
print(df['key2'].str[0])
# str之后和字符串本身索引方式相同
输出结果:
0 A
1 b
2 C
3 bbhello
4 123
5 NaN
6 hj
dtype: object
key1 key2
0 a hee
1 b fv
2 c w
3 d hija
4 e 123
5 f NaN
-----------------------------
0 A
1 b
2 C
3 b
4 1
5 NaN
6 h
dtype: object
0 A
1 b
2 C
3 bb
4 12
5 NaN
6 hj
dtype: object
0 h
1 f
2 w
3 h
4 1
5 NaN
Name: key2, dtype: object
三、pandas的合并merge、join
Pandas具有全功能的,高性能内存中连接操作,与SQL等关系数据库非常相似。
(1)合并merge
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=('_x', '_y'), copy=True, indicator=False)
--->>> merge的基本使用:
# merge合并 → 类似excel的vlookup
df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
print(df1)
print(df2)
print('---------------------------------')
print(pd.merge(df1, df2, on='key'))
# 左边是df1;右边是df2,根据key作为参考键进行合并
# on表示参考键
print('---------------------------------')
print(df3)
print(df4)
print('---------------------------------')
print(pd.merge(df3, df4, on=['key1','key2']))
# 多个链接键
# 就是参考键有两个key1和key2都能匹配上的就合并表格
输出结果:
A B key
0 A0 B0 K0
1 A1 B1 K1
2 A2 B2 K2
3 A3 B3 K3
C D key
0 C0 D0 K0
1 C1 D1 K1
2 C2 D2 K2
3 C3 D3 K3
---------------------------------
A B key C D
0 A0 B0 K0 C0 D0
1 A1 B1 K1 C1 D1
2 A2 B2 K2 C2 D2
3 A3 B3 K3 C3 D3
---------------------------------
A B key1 key2
0 A0 B0 K0 K0
1 A1 B1 K0 K1
2 A2 B2 K1 K0
3 A3 B3 K2 K1
C D key1 key2
0 C0 D0 K0 K0
1 C1 D1 K1 K0
2 C2 D2 K1 K0
3 C3 D3 K2 K0
---------------------------------
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A2 B2 K1 K0 C1 D1
2 A2 B2 K1 K0 C2 D2
--->>> merge的参数how,表示合并的方式:
# 参数how → 合并方式
df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
print(df3)
print(df4)
print('---------------------------------')
print(pd.merge(df3, df4,on=['key1','key2'], how = 'inner'))
print('------')
# how默认为inner → 取交集
print(pd.merge(df3, df4, on=['key1','key2'], how = 'outer'))
print('------')
# how=outer → 取并集,数据缺失范围NaN
print(pd.merge(df3, df4, on=['key1','key2'], how = 'left'))
print('------')
# how=left → 按照df3为参考合并,数据缺失范围NaN
# 以df3为主,保留df3有的,将df4合并到df3中
print(pd.merge(df3, df4, on=['key1','key2'], how = 'right'))
# how=right → 按照df4为参考合并,数据缺失范围NaN
# 以df4为主,保留df4有的,将df3合并到df4中
输出结果:
A B key1 key2
0 A0 B0 K0 K0
1 A1 B1 K0 K1
2 A2 B2 K1 K0
3 A3 B3 K2 K1
C D key1 key2
0 C0 D0 K0 K0
1 C1 D1 K1 K0
2 C2 D2 K1 K0
3 C3 D3 K2 K0
---------------------------------
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A2 B2 K1 K0 C1 D1
2 A2 B2 K1 K0 C2 D2
------
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A1 B1 K0 K1 NaN NaN
2 A2 B2 K1 K0 C1 D1
3 A2 B2 K1 K0 C2 D2
4 A3 B3 K2 K1 NaN NaN
5 NaN NaN K2 K0 C3 D3
------
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A1 B1 K0 K1 NaN NaN
2 A2 B2 K1 K0 C1 D1
3 A2 B2 K1 K0 C2 D2
4 A3 B3 K2 K1 NaN NaN
------
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A2 B2 K1 K0 C1 D1
2 A2 B2 K1 K0 C2 D2
3 NaN NaN K2 K0 C3 D3
--->>> merge的参数 left_on, right_on, left_index, right_index:
# 参数 left_on, right_on, left_index, right_index → 当键不为一个列时,可以单独设置左键与右键
df1 = pd.DataFrame({'lkey':list('bbacaab'),
'data1':range(7)})
df2 = pd.DataFrame({'rkey':list('abd'),
'date2':range(3)})
print(pd.merge(df1, df2, left_on='lkey', right_on='rkey'))
print('------')
# df1以‘lkey’为键,df2以‘rkey’为键
df1 = pd.DataFrame({'key':list('abcdfeg'),
'data1':range(7)})
df2 = pd.DataFrame({'date2':range(100,105)},
index = list('abcde'))
print(pd.merge(df1, df2, left_on='key', right_index=True))
# df1以‘key’为键,df2以index为键
# left_index:为True时,第一个df以index为键,默认False
# right_index:为True时,第二个df以index为键,默认False
# 所以left_on, right_on, left_index, right_index可以相互组合:
# left_on + right_on, left_on + right_index, left_index + right_on, left_index + right_index
输出结果:
data1 lkey date2 rkey
0 0 b 1 b
1 1 b 1 b
2 6 b 1 b
3 2 a 0 a
4 4 a 0 a
5 5 a 0 a
------
data1 key date2
0 0 a 100
1 1 b 101
2 2 c 102
3 3 d 103
5 5 e 104
--->>> merge的参数sort,排序
# 参数 sort
df1 = pd.DataFrame({'key':list('bbacaab'),
'data1':[1,3,2,4,5,9,7]})
df2 = pd.DataFrame({'key':list('abd'),
'date2':[11,2,33]})
print(df1)
print(df2)
x1 = pd.merge(df1,df2, on = 'key', how = 'outer')
x2 = pd.merge(df1,df2, on = 'key', sort=True, how = 'outer')
print(x1)
print(x2)
print('------')
# sort:按照字典顺序通过 连接键 对结果DataFrame进行排序。默认为False,设置为False会大幅提高性能
print(x2.sort_values('data1')) # 对data1进行排序
# 也可直接用Dataframe的排序方法:sort_values,sort_index
输出结果:
data1 key
0 1 b
1 3 b
2 2 a
3 4 c
4 5 a
5 9 a
6 7 b
date2 key
0 11 a
1 2 b
2 33 d
data1 key date2
0 1.0 b 2.0
1 3.0 b 2.0
2 7.0 b 2.0
3 2.0 a 11.0
4 5.0 a 11.0
5 9.0 a 11.0
6 4.0 c NaN
7 NaN d 33.0
data1 key date2
0 2.0 a 11.0
1 5.0 a 11.0
2 9.0 a 11.0
3 1.0 b 2.0
4 3.0 b 2.0
5 7.0 b 2.0
6 4.0 c NaN
7 NaN d 33.0
------
data1 key date2
3 1.0 b 2.0
0 2.0 a 11.0
4 3.0 b 2.0
6 4.0 c NaN
1 5.0 a 11.0
5 7.0 b 2.0
2 9.0 a 11.0
7 NaN d 33.0
(2)join链接
# pd.join() → 直接通过索引链接
left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=['K0', 'K1', 'K2'])
right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
'D': ['D0', 'D2', 'D3']},
index=['K0', 'K2', 'K3'])
print(left)
print(right)
print(left.join(right))
print(left.join(right, how='outer'))
print('-----')
# 等价于:pd.merge(left, right, left_index=True, right_index=True, how='outer')
df1 = pd.DataFrame({'key':list('bbacaab'),
'data1':[1,3,2,4,5,9,7]})
df2 = pd.DataFrame({'key':list('abd'),
'date2':[11,2,33]})
print(df1)
print(df2)
print(pd.merge(df1, df2, left_index=True, right_index=True, suffixes=('_1', '_2')))
print(df1.join(df2['date2']))
print('-----')
# suffixes=('_x', '_y')默认
left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key': ['K0', 'K1', 'K0', 'K1']})
right = pd.DataFrame({'C': ['C0', 'C1'],
'D': ['D0', 'D1']},
index=['K0', 'K1'])
print(left)
print(right)
print(left.join(right, on = 'key'))
# 等价于pd.merge(left, right, left_on='key', right_index=True, how='left', sort=False);
# left的‘key’和right的index
输出结果:
A B
K0 A0 B0
K1 A1 B1
K2 A2 B2
C D
K0 C0 D0
K2 C2 D2
K3 C3 D3
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
K3 NaN NaN C3 D3
-----
data1 key
0 1 b
1 3 b
2 2 a
3 4 c
4 5 a
5 9 a
6 7 b
date2 key
0 11 a
1 2 b
2 33 d
data1 key_1 date2 key_2
0 1 b 11 a
1 3 b 2 b
2 2 a 33 d
data1 key date2
0 1 b 11.0
1 3 b 2.0
2 2 a 33.0
3 4 c NaN
4 5 a NaN
5 9 a NaN
6 7 b NaN
-----
A B key
0 A0 B0 K0
1 A1 B1 K1
2 A2 B2 K0
3 A3 B3 K1
C D
K0 C0 D0
K1 C1 D1
A B key C D
0 A0 B0 K0 C0 D0
1 A1 B1 K1 C1 D1
2 A2 B2 K0 C0 D0
3 A3 B3 K1 C1 D1
四、pandas的连接concat与修补combine_first
连接是指沿轴执行连接操作。
(1)连接concat
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)
--->>> 参数axis:
# 连接:concat
# pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)
s1 = pd.Series([1,2,3])
s2 = pd.Series([2,3,4])
s3 = pd.Series([1,2,3],index=list('ach'))
s4 = pd.Series([2,3,4],index=['b','e','d'])
#print(s4)
# 【参数axis】
# concat连接s1和s2,
# 参数axis=0,是行+行,返回series
sc = pd.concat([s1,s2])
print(sc,type(sc))
# concat连接s3和s4
sc2 = pd.concat([s3,s4])
print(sc2.sort_index()) # 对连接的series的index排序
print('--------------------')
# 参数axis=1,是列+列,返回dataframe
df = pd.concat([s1,s2],axis=1)
print(df,type(df))
输出结果:
0 1
1 2
2 3
0 2
1 3
2 4
dtype: int64
a 1
b 2
c 2
d 4
e 3
h 3
dtype: int64
--------------------
0 1
0 1 2
1 2 3
2 3 4
--->>> 参数join和join_axes,表示连接方式:
# 连接方式:join,join_axes
s1 = pd.Series([1,2,3],index=list('abc'))
s2 = pd.Series([2,3,4],index=list('bcd'))
print(s1)
print(s2)
print('---------------')
#【参数join】
# 参数join默认为outer,取联合;join为inner取交集。
print(pd.concat([s1,s2],axis=1,join='inner'))
print('---------------')
# 【参数join_axes】
# 参数join_axes默认为None,若定义join_axes,可以指定联合的index
print(pd.concat([s1,s2],axis=1,join_axes=[['a','b','c']]))
输出结果:
a 1
b 2
c 3
dtype: int64
b 2
c 3
d 4
dtype: int64
---------------
0 1
b 2 2
c 3 3
---------------
0 1
a 1 NaN
b 2 2.0
c 3 3.0
--->>> 参数keys:
# 覆盖列名:keys
s1 = pd.Series([1,2,3],index=list('abc'))
s2 = pd.Series([2,3,4],index=list('ejh'))
sc = pd.concat([s1,s2])
print(sc)
# 【参数keys】
# 参数keys默认None;
# 若定义keys参数,以序列形式,可以使用传递的键作为最外层构建层次索引
sc = pd.concat([s1,s2],keys=['one','two'])
print(sc,type(sc))
print(sc.index)
# axis=1,且利用key参数覆盖列名;
sc2 = pd.concat([s1,s2],axis=1,keys=['one','two'])
print(sc2,type(sc2))
输出结果:
a 1
b 2
c 3
e 2
j 3
h 4
dtype: int64
one a 1
b 2
c 3
two e 2
j 3
h 4
dtype: int64
MultiIndex(levels=[['one', 'two'], ['a', 'b', 'c', 'e', 'h', 'j']],
labels=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 3, 5, 4]])
one two
a 1.0 NaN
b 2.0 NaN
c 3.0 NaN
e NaN 2.0
h NaN 4.0
j NaN 3.0
(2)修补pd.combine_first()
# 修补 pd.combine_first()
df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],[np.nan, 7., np.nan]])
df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],index=[1, 2])
print(df1)
print(df2)
print('----------------------')
print(df1.combine_first(df2))
# pd.combine_first()修补,根据index,用df2将df1的空值替代上
# 如果df2的index多于df1,则更新到df1上,比如index=['a',1]
print('----------------------')
df1.update(df2)
print(df1)
# update,直接df2覆盖df1,相同index位置
输出结果:
0 1 2
0 NaN 3.0 5.0
1 -4.6 NaN NaN
2 NaN 7.0 NaN
0 1 2
1 -42.6 NaN -8.2
2 -5.0 1.6 4.0
----------------------
0 1 2
0 NaN 3.0 5.0
1 -4.6 NaN -8.2
2 -5.0 7.0 4.0
----------------------
0 1 2
0 NaN 3.0 5.0
1 -42.6 NaN -8.2
2 -5.0 1.6 4.0
五、pandas的去重及替换
(1)去重.duplicated
# 去重 .duplicated
# 创建一个含有重复元素的Series
s = pd.Series([1,1,1,1,2,2,2,3,4,5,5,5,5])
print(s)
print('-------------')
# duplicated()去重
print(s.duplicated()) # 判断是否重复,返回布尔型
print(s[s.duplicated()==False]) # 输出=False的,也就是不重复的
print('------------')
# drop.duplicates移除重复
# 参数inplace,表是否替换原值,默认False不替换
s_re = s.drop_duplicates()
print(s_re)
print('---------------')
print('---------------')
# Dataframe中使用duplicated
# 创建一个含有重复元素的dataframe
df = pd.DataFrame({'key1':['a','a',3,4,5],
'key2':['a','a','b','b','c']})
print(df)
print('---------------')
print(df.duplicated())
# 判断是aa是否重复,3b是否重复,是key1+key2结合一起判断的
print(df['key2'].duplicated()) # 单判断key2这列的元素是否重复
输出结果:
0 1
1 1
2 1
3 1
4 2
5 2
6 2
7 3
8 4
9 5
10 5
11 5
12 5
dtype: int64
-------------
0 False
1 True
2 True
3 True
4 False
5 True
6 True
7 False
8 False
9 False
10 True
11 True
12 True
dtype: bool
0 1
4 2
7 3
8 4
9 5
dtype: int64
------------
0 1
4 2
7 3
8 4
9 5
dtype: int64
---------------
---------------
key1 key2
0 a a
1 a a
2 3 b
3 4 b
4 5 c
---------------
0 False
1 True
2 False
3 False
4 False
dtype: bool
0 False
1 True
2 False
3 True
4 False
Name: key2, dtype: bool
(2)替换.replace
# 替换 .replace
s = pd.Series(list('ascaazsd'))
print(s)
print('---------')
print(s.replace('a', np.nan)) # 用np.nan替换字符串"a"
print('---------')
# 可一次性替换一个值或多个值
print(s.replace(['a','s'] ,np.nan))
print('---------')
# 可传入列表或字典
print(s.replace({'a':'hello world!','s':123}))
# 'a':'hello world!' → a 用hello world替换
输出结果:
0 a
1 s
2 c
3 a
4 a
5 z
6 s
7 d
dtype: object
---------
0 NaN
1 s
2 c
3 NaN
4 NaN
5 z
6 s
7 d
dtype: object
---------
0 NaN
1 NaN
2 c
3 NaN
4 NaN
5 z
6 NaN
7 d
dtype: object
---------
0 hello world!
1 123
2 c
3 hello world!
4 hello world!
5 z
6 123
7 d
dtype: object
六、数据分组groupby(重点掌握)
分组统计,groupby功能:① 根据某些条件将数据拆分成组;② 对每个组独立应用函数;③ 将结果合并到一个数据结构中。
Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。
*df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, *kwargs)
--->>> 分组:
# 分组 - groupby()
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)})
print(df)
print('------')
print(df.groupby('A'),type(df.groupby('A')))
print('------')
# 直接分组得到一个groupby对象,是一个中间数据,没有进行计算
a = df.groupby('A').mean() # 以A分组,算平均值
print(a,type(a))
print('------')
b = df.groupby(['A','B']).mean() # 以A、B分组,算平均值
print(b,type(b))
print('------')
c = df.groupby('A')['D'].mean() # 以A分组,再取个D列求D的平均值
print(c)
# 通过分组后的计算,得到一个新的dataframe
# 默认axis = 0,以行来分组
# 可单个或多个([])列分组
输出结果:
A B C D
0 foo one -0.644577 1.118908
1 bar one 1.179229 -0.386515
2 foo two -1.060731 0.536817
3 bar three 1.151450 -1.321295
4 foo two 0.388789 2.147647
5 bar two 0.059214 1.008346
6 foo one 1.364315 -0.617321
7 foo three -0.834223 -0.671149
------
------
C D
A
bar 0.796631 -0.233155
foo -0.157285 0.502980
------
C D
A B
bar one 1.179229 -0.386515
three 1.151450 -1.321295
two 0.059214 1.008346
foo one 0.359869 0.250794
three -0.834223 -0.671149
two -0.335971 1.342232
------
A
bar -0.233155
foo 0.502980
Name: D, dtype: float64
--->>> 分组迭代对象:
# 分组 - 可迭代对象
# 创建df
df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
print(df)
print(df.groupby('X'), type(df.groupby('X')))
print('-----')
# 可迭代对象
print(list(df.groupby('X')), '→ 可迭代对象,直接生成list\n')
print(list(df.groupby('X'))[0], '→ 以元祖形式显示\n')
for n,g in df.groupby('X'):
print(n)
print(g)
print('###')
print('-----')
# n是组名,g是分组后的Dataframe
# .get_group()提取分组后的组
print(df.groupby(['X']).get_group('A'),'\n') # 提取分组后的A组
print(df.groupby(['X']).get_group('B'),'\n') # 提取分组后的B组
print('-----')
# .groups:将分组后的groups转为dict
# 可以字典索引方法来查看groups里的元素
grouped = df.groupby(['X'])
print(grouped)
print(grouped.groups) # 以X列分组后用.grouped转为字典dict
print(grouped.groups['A'],type(grouped.groups['A'])) # 提取字典里的key为A的元素
print('-----')
# .size():查看分组后的长度
sz = grouped.size()
print(sz,type(sz))
print('----------------------------------')
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)})
print(df)
print('---------')
grouped = df.groupby(['A','B']).groups # 以A、B列分组,分组后组成dict
print(grouped,type(grouped))
print('----')
print(grouped[('foo', 'three')]) # 提取grouped字典key为('foo', 'three')的元素
输出结果:
X Y
0 A 1
1 B 4
2 A 3
3 B 2
-----
[('A', X Y
0 A 1
2 A 3), ('B', X Y
1 B 4
3 B 2)] → 可迭代对象,直接生成list
('A', X Y
0 A 1
2 A 3) → 以元祖形式显示
A
X Y
0 A 1
2 A 3
###
B
X Y
1 B 4
3 B 2
###
-----
X Y
0 A 1
2 A 3
X Y
1 B 4
3 B 2
-----
{'A': Int64Index([0, 2], dtype='int64'), 'B': Int64Index([1, 3], dtype='int64')}
Int64Index([0, 2], dtype='int64')
-----
X
A 2
B 2
dtype: int64
----------------------------------
A B C D
0 foo one -1.145245 0.282188
1 bar one 1.098816 -1.229021
2 foo two -0.202471 1.313067
3 bar three 0.423064 -0.944102
4 foo two 1.035012 -0.159363
5 bar two 2.586997 -0.870078
6 foo one 0.549764 -0.323518
7 foo three -2.402178 0.990989
---------
{('foo', 'one'): Int64Index([0, 6], dtype='int64'), ('foo', 'three'): Int64Index([7], dtype='int64'), ('bar', 'three'): Int64Index([3], dtype='int64'), ('foo', 'two'): Int64Index([2, 4], dtype='int64'), ('bar', 'one'): Int64Index([1], dtype='int64'), ('bar', 'two'): Int64Index([5], dtype='int64')}
----
Int64Index([7], dtype='int64')
--->>> 其他轴上的分组:
# 其他轴上的分组
df = pd.DataFrame({'data1':np.random.rand(2),
'data2':np.random.rand(2),
'key1':['a','b'],
'key2':['one','two']})
print(df)
print(df.dtypes)
print('-----')
# 按照值类型分列
for n,p in df.groupby(df.dtypes, axis=1):
print(n)
print(p)
print('##')
输出结果:
data1 data2 key1 key2
0 0.269405 0.236738 a one
1 0.000449 0.503876 b two
data1 float64
data2 float64
key1 object
key2 object
dtype: object
-----
float64
data1 data2
0 0.269405 0.236738
1 0.000449 0.503876
##
object
key1 key2
0 a one
1 b two
##
--->>> 过字典或者Series分组:(特定分组的时候会比较方便)
# 通过字典或者Series分组
df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'])
print(df)
print('-----')
# 创建字典
dic = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
print(dic,type(dic))
# 通过字典分组
dic_by = df.groupby(dic,axis = 1).sum()
print(dic_by)
print('-----')
# dic中,a、b列对应的为one,c、d列对应的为two,以字典来分组
# 创建series
s = pd.Series(dic)
print(s,'\n')
print(s.groupby(s).count())
# s中,index中a、b对应的为one,c、d对应的为two,以Series来分组
输出结果:
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
-----
{'d': 'two', 'b': 'one', 'c': 'two', 'a': 'one', 'e': 'three'}
one two
0 1 5
1 9 13
2 17 21
3 25 29
-----
a one
b one
c two
d two
e three
dtype: object
one 2
three 1
two 2
dtype: int64
--->>> 通过函数分组:
# 通过函数分组
df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'],
index = ['abc','bcd','aa','b'])
print(df,'\n')
print(df.groupby(len).sum())
# 按照字母长度分组
a b c d
abc 0 1 2 3
bcd 4 5 6 7
aa 8 9 10 11
b 12 13 14 15
a b c d
1 12 13 14 15
2 8 9 10 11
3 4 6 8 10
--->>> 分组计算函数方法:
# 分组计算函数方法
s = pd.Series([1, 2, 3, 10, 20, 30], index = [1, 2, 3, 1, 2, 3])
print(s,'\n')
grouped = s.groupby(level=0)
print(grouped,'\n')
# 唯一索引用.groupby(level=0),将同一个index的分为一组
print(grouped.first(),'→ first:非NaN的第一个值\n')
print(grouped.last(),'→ last:非NaN的最后一个值\n')
print(grouped.sum(),'→ sum:非NaN的和\n')
print(grouped.mean(),'→ mean:非NaN的平均值\n')
print(grouped.median(),'→ median:非NaN的算术中位数\n')
print(grouped.count(),'→ count:非NaN的值\n')
print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
print(grouped.prod(),'→ prod:非NaN的积\n')
输出结果:
1 1
2 2
3 3
1 10
2 20
3 30
dtype: int64
1 1
2 2
3 3
dtype: int64 → first:非NaN的第一个值
1 10
2 20
3 30
dtype: int64 → last:非NaN的最后一个值
1 11
2 22
3 33
dtype: int64 → sum:非NaN的和
1 5.5
2 11.0
3 16.5
dtype: float64 → mean:非NaN的平均值
1 5.5
2 11.0
3 16.5
dtype: float64 → median:非NaN的算术中位数
1 2
2 2
3 2
dtype: int64 → count:非NaN的值
1 1
2 2
3 3
dtype: int64 → min、max:非NaN的最小值、最大值
1 6.363961
2 12.727922
3 19.091883
dtype: float64 → std,var:非NaN的标准差和方差
1 10
2 40
3 90
dtype: int64 → prod:非NaN的积
--->>> 多函数计算:agg()
# 多函数计算:agg()
# 多函数计算可以让分组数据同时计算两个以上的统计
df = pd.DataFrame({'a':[1,1,2,2],
'b':np.random.rand(4),
'c':np.random.rand(4),
'd':np.random.rand(4),})
print(df,'\n')
print(df.groupby('a').agg(['mean',np.sum]))
print(df.groupby('a')['b'].agg({'result1':np.mean,
'result2':np.sum}))
# 函数写法可以用str,或者np.方法
# 可以通过list,dict传入,当用dict时,key名为columns
输出结果:
a b c d
0 1 0.689856 0.212391 0.575196
1 1 0.516206 0.871239 0.340175
2 2 0.440666 0.428301 0.573359
3 2 0.211181 0.900975 0.845924
b c d
mean sum mean sum mean sum
a
1 0.603031 1.206062 0.541815 1.083630 0.457686 0.915371
2 0.325924 0.651847 0.664638 1.329276 0.709641 1.419282
result2 result1
a
1 1.206062 0.603031
2 0.651847 0.325924
七、分组转换及一般性“拆分-应用-合并”
(1)数据分组转换transform
# 数据分组转换,transform
df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df,'\n')
k_mean = df.groupby('key1').mean() # 以key1分组,求平均值
print(k_mean,'\n')
print(pd.merge(df,k_mean,left_on='key1',right_index=True).add_prefix('mean_')) # .add_prefix('mean_'):添加前缀
print('---------------')
# 通过分组、合并,得到一个包含均值的Dataframe
print(df.groupby('key2').mean(),'\n') # 按照key2分组求均值
print(df.groupby('key2').transform(np.mean))
# data1、data2每个位置元素取对应分组列的均值
# 字符串不能进行计算
输出结果:
data1 data2 key1 key2
0 0.295972 0.857439 a one
1 0.934285 0.278705 a two
2 0.302457 0.844987 b one
3 0.248708 0.549459 b two
4 0.978329 0.691800 a one
data1 data2
key1
a 0.736195 0.609315
b 0.275582 0.697223
mean_data1_x mean_data2_x mean_key1 mean_key2 mean_data1_y mean_data2_y
0 0.295972 0.857439 a one 0.736195 0.609315
1 0.934285 0.278705 a two 0.736195 0.609315
4 0.978329 0.691800 a one 0.736195 0.609315
2 0.302457 0.844987 b one 0.275582 0.697223
3 0.248708 0.549459 b two 0.275582 0.697223
---------------
data1 data2
key2
one 0.525586 0.798075
two 0.591497 0.414082
data1 data2
0 0.525586 0.798075
1 0.591497 0.414082
2 0.525586 0.798075
3 0.591497 0.414082
4 0.525586 0.798075
(2)一般化groupby方法:apply(运用较广泛)
# 一般化Groupby方法:apply
# apply直接运行其中的函数
df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df.groupby('key1').apply(lambda x: x.describe()))
# apply直接运行其中的函数
# 这里为匿名函数,直接描述分组后的统计量
def f_df1(d,n):
return(d.sort_index()[:n])
def f_df2(d,k1):
return(d[k1])
print(df.groupby('key1').apply(f_df1,2),'\n')
print(df.groupby('key1').apply(f_df2,'data2'))
print(type(df.groupby('key1').apply(f_df2,'data2')))
# f_df1函数:返回排序后的前n行数据
# f_df2函数:返回分组后表的k1列,结果为Series,层次化索引
# 直接运行f_df函数
# 参数直接写在后面,也可以为.apply(f_df,n = 2))
输出结果:
data1 data2
key1
a count 3.000000 3.000000
mean 0.260004 0.604611
std 0.423720 0.200435
min 0.007524 0.397114
25% 0.015412 0.508344
50% 0.023299 0.619574
75% 0.386244 0.708360
max 0.749189 0.797146
b count 2.000000 2.000000
mean 0.379854 0.639659
std 0.043777 0.308873
min 0.348899 0.421253
25% 0.364377 0.530456
50% 0.379854 0.639659
75% 0.395332 0.748862
max 0.410809 0.858065
data1 data2 key1 key2
key1
a 0 0.023299 0.397114 a one
1 0.007524 0.797146 a two
b 2 0.410809 0.421253 b one
3 0.348899 0.858065 b two
key1
a 0 0.397114
1 0.797146
4 0.619574
b 2 0.421253
3 0.858065
Name: data2, dtype: float64
八、透视表及交叉表
类似excel数据透视 - pivot table / crosstab
(1)透视表pivot_table
透视表就是做数据透视。
pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
# 透视表:pivot_table
# pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
date = ['2017-5-1','2017-5-2','2017-5-3']*3
rng = pd.to_datetime(date)
df = pd.DataFrame({'date':rng,
'key':list('abcdabcda'),
'values':np.random.rand(9)*10})
print(df)
print('-----')
print(pd.pivot_table(df,values='values',index='date',columns='key',aggfunc=np.sum),'\n')
# data:DataFrame对象
# values:要聚合的列或列的列表
# index:数据透视表的index,从原数据的列中筛选
# columns:数据透视表的columns,从原数据的列中筛选
# aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
print(pd.pivot_table(df, values = 'values', index = ['date','key'], aggfunc=len))
# 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
# aggfunc=len(或者count):计数
输出结果:
date key values
0 2017-05-01 a 1.978948
1 2017-05-02 b 6.444399
2 2017-05-03 c 5.816060
3 2017-05-01 d 4.127823
4 2017-05-02 a 7.059673
5 2017-05-03 b 4.657516
6 2017-05-01 c 3.127164
7 2017-05-02 d 0.198809
8 2017-05-03 a 1.435535
-----
key a b c d
date
2017-05-01 1.978948 NaN 3.127164 4.127823
2017-05-02 7.059673 6.444399 NaN 0.198809
2017-05-03 1.435535 4.657516 5.816060 NaN
values
date key
2017-05-01 a 1.0
c 1.0
d 1.0
2017-05-02 a 1.0
b 1.0
d 1.0
2017-05-03 a 1.0
b 1.0
c 1.0
(2)交叉表crosstab
交叉表做因子频率计算。
pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
# 交叉表:crosstab,统计频率的时候用交叉表,如字符串只能计算频率
# 默认情况下,crosstab计算因子的频率表,比如用于str的数据透视分析
# pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
df = pd.DataFrame({'A': [1, 2, 2, 2, 2],
'B': [3, 3, 4, 4, 4],
'C': [1, 1, np.nan, 1, 1]})
print(df)
print('-----')
print(pd.crosstab(df['A'],df['B']))
#print('-----')
# 如果crosstab只接收两个Series,它将提供一个频率表。
# 用A的唯一值,统计B唯一值的出现次数
# 返回的频率表意思:B=3,A=1的频率为1,以此类推。
print(pd.crosstab(df['A'],df['B'],normalize=True))
print('-----')
# normalize:默认False,将所有值除以值的总和进行归一化 → 为True时候显示百分比
# 返回的频率表是B=3,A=1的频率为1,总和为1+0+1+3=5,1/5=0.2
print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum))
print('-----')
# values:可选,根据因子聚合的值数组
# aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算
# 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum, margins=True))
# margins:布尔值,默认值False,添加行/列边距(小计求和)
输出结果:
A B C
0 1 3 1.0
1 2 3 1.0
2 2 4 NaN
3 2 4 1.0
4 2 4 1.0
-----
B 3 4
A
1 1 0
2 1 3
B 3 4
A
1 0.2 0.0
2 0.2 0.6
-----
B 3 4
A
1 1.0 NaN
2 1.0 2.0
-----
B 3 4 All
A
1 1.0 NaN 1.0
2 1.0 2.0 3.0
All 2.0 2.0 4.0
九、数据读取
(1)读取普通分隔数据read_table
读取普通分隔数据read_table,主要用于读取简单的数据,可以读取txt,csv。
# 读取普通分隔数据:read_table
# 可以读取txt,csv
import os # 调用os模块
os.chdir(r'C:\Users\Yeung\Desktop') # 导入路径
data1 = pd.read_table('data1.txt', delimiter=',')
print(data1,'\n')
# delimiter:用于拆分的字符,也可以用sep:sep = ','
data2 = pd.read_table('data1.txt',delimiter=',',header=1)
print(data2,'\n')
# 参数header:表示用做列名的序号,默认为0(第一行),这里data2指定用第二行为列名
# 参数index_col:表示指定某列为行索引,默认index_col=None,自动用0, 1, 2,.....数字作索引
# read_table主要用于读取简单的数据,txt/csv(使用较少)
输出结果:
va1 va2 va3 va4
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
1 2 3 4
0 2 3 4 5
1 3 4 5 6
2 4 5 6 7
(2)读取csv数据read_csv
csv数据其实就是逗号分隔符类的数据。
# 读取csv数据:read_csv
# 先熟悉一下excel怎么导出csv——excel另存csv即可,要注意选择的编码是什么
data2 = pd.read_csv('data2.csv',engine = 'python',encoding= 'utf8')
print(data2.head(20))
print(type(data2))
# 参数engine:使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
# 参数encoding:指定字符集类型,即编码,通常指定为'utf8';如果发现读取有问题就把这个参数加上
# 大多数情况先将excel导出csv,再读取
(3)读取excel数据read_excel
数据是报表excel一般是已经处理过的数据。
# 读取excel数据:read_excel
data3 = pd.read_excel('data3.xlsx',sheet_name='中国人民共和国地市级党委书记数据库(2000-10)',header=0)
print(data3)
# io :文件路径。
# sheet_name:返回多表使用sheetname=[0,1],若sheetname=None是返回全表 → ① int/string 返回的是dataframe ②而none和list返回的是dict
# header:指定列名行,默认0,即取第一行
# index_col:指定列为索引列,也可以使用u”strings”
输出结果:
输出结果截图.png