文章目录
-
-
- pandas高级操作
-
- 替换操作
- 映射操作
- 运算工具
- 排序实现的随机抽样
- 数据的分类处理
- 高级数据聚合
- 数据加载
- 透视表
- 交叉表
pandas高级操作
import pandas as pd
import numpy as np
from pandas import DataFrame
替换操作
df = DataFrame(data=np.random.randint(0,20,size=(8,5)))
df
|
0 |
1 |
2 |
3 |
4 |
0 |
17 |
0 |
17 |
11 |
6 |
1 |
8 |
3 |
7 |
7 |
3 |
2 |
9 |
13 |
4 |
19 |
3 |
3 |
12 |
3 |
0 |
10 |
16 |
4 |
8 |
5 |
5 |
4 |
14 |
5 |
14 |
18 |
2 |
1 |
3 |
6 |
14 |
6 |
8 |
15 |
5 |
7 |
2 |
7 |
7 |
18 |
11 |
df.replace(to_replace=1,value='one')
|
0 |
1 |
2 |
3 |
4 |
0 |
17 |
0 |
17 |
11 |
6 |
1 |
8 |
3 |
7 |
7 |
3 |
2 |
9 |
13 |
4 |
19 |
3 |
3 |
12 |
3 |
0 |
10 |
16 |
4 |
8 |
5 |
5 |
4 |
14 |
5 |
14 |
18 |
2 |
one |
3 |
6 |
14 |
6 |
8 |
15 |
5 |
7 |
2 |
7 |
7 |
18 |
11 |
df.replace(to_replace={1:'one',3:'three'})
|
0 |
1 |
2 |
3 |
4 |
0 |
17 |
0 |
17 |
11 |
6 |
1 |
8 |
three |
7 |
7 |
three |
2 |
9 |
13 |
4 |
19 |
three |
3 |
12 |
three |
0 |
10 |
16 |
4 |
8 |
5 |
5 |
4 |
14 |
5 |
14 |
18 |
2 |
one |
three |
6 |
14 |
6 |
8 |
15 |
5 |
7 |
2 |
7 |
7 |
18 |
11 |
df.replace(to_replace={3:17},value='one')
|
0 |
1 |
2 |
3 |
4 |
0 |
13 |
10 |
14 |
2 |
17 |
1 |
17 |
2 |
4 |
one |
9 |
2 |
2 |
3 |
10 |
one |
13 |
3 |
17 |
15 |
19 |
13 |
15 |
4 |
10 |
5 |
17 |
7 |
4 |
5 |
3 |
2 |
0 |
0 |
13 |
6 |
6 |
8 |
0 |
16 |
1 |
7 |
15 |
13 |
10 |
6 |
18 |
映射操作
dic = {
'name':['张三','李四','王五','张三'],
'salary':[5000,6000,5500,5000]
}
df = DataFrame(data=dic)
df
|
name |
salary |
0 |
张三 |
5000 |
1 |
李四 |
6000 |
2 |
王五 |
5500 |
3 |
张三 |
5000 |
dic = {
'李四':'Jerry',
'王五':'Jack',
'张三':'Tom'
}
e_name = df['name'].map(dic)
df['e_name'] = e_name
df
|
name |
salary |
e_name |
0 |
张三 |
5000 |
Tom |
1 |
李四 |
6000 |
Jerry |
2 |
王五 |
5500 |
Jack |
3 |
张三 |
5000 |
Tom |
- map是Series的方法,只能被Series调用
运算工具
- 超过3000部分的钱缴纳50%的税,计算每个人的税后薪资
def after_sal(s):
return s - (s-3000)*0.5
after_salary = df['salary'].map(after_sal)
df['after_salary'] = after_salary
df
|
name |
salary |
e_name |
after_salary |
0 |
张三 |
5000 |
Tom |
4000.0 |
1 |
李四 |
6000 |
Jerry |
4500.0 |
2 |
王五 |
5500 |
Jack |
4250.0 |
3 |
张三 |
5000 |
Tom |
4000.0 |
- Series的方法apply也可以像map一样充当运算工具
def after_sal(s):
return s - (s-3000)*0.5
after_salary = df['salary'].apply(after_sal)
after_salary
0 4000.0
1 4500.0
2 4250.0
3 4000.0
Name: salary, dtype: float64
排序实现的随机抽样
- take()
- np.random.permutation(n):返回0-(n-1)之间的随机序列
df = DataFrame(data=np.random.random(size=(100,3)),columns=['A','B','C'])
df.head()
|
A |
B |
C |
0 |
0.443835 |
0.973331 |
0.626923 |
1 |
0.366619 |
0.225035 |
0.719683 |
2 |
0.431639 |
0.154259 |
0.051419 |
3 |
0.406994 |
0.065048 |
0.145229 |
4 |
0.965849 |
0.385788 |
0.208316 |
df.take(np.random.permutation(100),axis=0)
|
A |
B |
C |
88 |
0.882121 |
0.368332 |
0.158629 |
96 |
0.319008 |
0.251546 |
0.009901 |
28 |
0.696431 |
0.178469 |
0.125718 |
23 |
0.268010 |
0.639662 |
0.137387 |
22 |
0.599899 |
0.089535 |
0.930574 |
... |
... |
... |
... |
50 |
0.468952 |
0.562839 |
0.671872 |
79 |
0.237526 |
0.228043 |
0.699325 |
87 |
0.932147 |
0.394211 |
0.540368 |
90 |
0.980401 |
0.823402 |
0.624730 |
92 |
0.699101 |
0.108088 |
0.542962 |
100 rows × 3 columns
df.take(np.random.permutation(100),axis=0).take(indices=np.random.permutation(3),axis=1)
|
B |
A |
C |
46 |
0.274198 |
0.689843 |
0.119163 |
6 |
0.493573 |
0.854749 |
0.134710 |
55 |
0.572823 |
0.159019 |
0.124300 |
65 |
0.982499 |
0.822922 |
0.788931 |
5 |
0.578393 |
0.904401 |
0.866710 |
... |
... |
... |
... |
30 |
0.734058 |
0.948066 |
0.029316 |
59 |
0.103037 |
0.748319 |
0.025966 |
48 |
0.988017 |
0.194801 |
0.162126 |
80 |
0.594385 |
0.471618 |
0.945606 |
70 |
0.750110 |
0.592528 |
0.470297 |
100 rows × 3 columns
df.take(np.random.permutation(100),axis=0).take(indices=np.random.permutation(3),axis=1)[0:5]
|
A |
B |
C |
38 |
0.605719 |
0.843236 |
0.339796 |
32 |
0.779512 |
0.944551 |
0.109526 |
70 |
0.243308 |
0.799665 |
0.374344 |
37 |
0.929103 |
0.907324 |
0.259208 |
21 |
0.963018 |
0.868906 |
0.874337 |
数据的分类处理
-
数据分类处理的核心:
- groupby()函数
- groups属性查看分组情况
df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'],
'price':[4,3,3,2.5,4,2],
'color':['red','yellow','yellow','green','green','green'],
'weight':[12,20,50,30,20,44]})
df
|
item |
price |
color |
weight |
0 |
Apple |
4.0 |
red |
12 |
1 |
Banana |
3.0 |
yellow |
20 |
2 |
Orange |
3.0 |
yellow |
50 |
3 |
Banana |
2.5 |
green |
30 |
4 |
Orange |
4.0 |
green |
20 |
5 |
Apple |
2.0 |
green |
44 |
df.groupby(by='item')
df.groupby(by='item').groups
{'Apple': [0, 5], 'Banana': [1, 3], 'Orange': [2, 4]}
df.groupby(by='item').mean()
df.groupby(by='item').mean()['price']
item
Apple 3.00
Banana 2.75
Orange 3.50
Name: price, dtype: float64
df.groupby(by='item')['price'].mean()
item
Apple 3.00
Banana 2.75
Orange 3.50
Name: price, dtype: float64
df.groupby(by=['item','color'])
df.groupby(by=['color','item']).sum()
|
|
price |
weight |
color |
item |
|
|
green |
Apple |
2.0 |
44 |
Banana |
2.5 |
30 |
Orange |
4.0 |
20 |
red |
Apple |
4.0 |
12 |
yellow |
Banana |
3.0 |
20 |
Orange |
3.0 |
50 |
mean_price_s = df.groupby(by='item')['price'].mean()
mean_price_s
item
Apple 3.00
Banana 2.75
Orange 3.50
Name: price, dtype: float64
dic = mean_price_s.to_dict()
df['mean_price'] = df['item'].map(dic)
df
|
item |
price |
color |
weight |
mean_price |
0 |
Apple |
4.0 |
red |
12 |
3.00 |
1 |
Banana |
3.0 |
yellow |
20 |
2.75 |
2 |
Orange |
3.0 |
yellow |
50 |
3.50 |
3 |
Banana |
2.5 |
green |
30 |
2.75 |
4 |
Orange |
4.0 |
green |
20 |
3.50 |
5 |
Apple |
2.0 |
green |
44 |
3.00 |
mean_weight_s = df.groupby(by='color')['weight'].mean()
dic = mean_weight_s.to_dict()
mean_weight = df['color'].map(dic)
df['mean_weight'] = mean_weight
df
|
item |
price |
color |
weight |
mean_price |
mean_weight |
0 |
Apple |
4.0 |
red |
12 |
3.00 |
12.000000 |
1 |
Banana |
3.0 |
yellow |
20 |
2.75 |
35.000000 |
2 |
Orange |
3.0 |
yellow |
50 |
3.50 |
35.000000 |
3 |
Banana |
2.5 |
green |
30 |
2.75 |
31.333333 |
4 |
Orange |
4.0 |
green |
20 |
3.50 |
31.333333 |
5 |
Apple |
2.0 |
green |
44 |
3.00 |
31.333333 |
高级数据聚合
- 使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算
- df.groupby(‘item’)[‘price’].sum() <==> df.groupby(‘item’)[‘price’].apply(sum)
- transform和apply都会进行运算,在transform或者apply中传入函数即可
- transform和apply也可以传入一个lambda表达式
def my_mean(p):
sum = 0
for i in p:
sum += i
return sum / len(p)
df.groupby(by='item')['price'].transform(my_mean)
0 3.00
1 2.75
2 3.50
3 2.75
4 3.50
5 3.00
Name: price, dtype: float64
df.groupby(by='item')['price'].apply(my_mean)
item
Apple 3.00
Banana 2.75
Orange 3.50
Name: price, dtype: float64
数据加载
df = pd.read_csv('./data/type-.txt')
df
|
你好-我好-他也好 |
0 |
也许-大概-有可能 |
1 |
然而-未必-不见得 |
df = pd.read_csv('./data/type-.txt',sep='-')
df
|
你好 |
我好 |
他也好 |
0 |
也许 |
大概 |
有可能 |
1 |
然而 |
未必 |
不见得 |
df = pd.read_csv('./data/type-.txt',sep='-',header=None)
df
|
0 |
1 |
2 |
0 |
你好 |
我好 |
他也好 |
1 |
也许 |
大概 |
有可能 |
2 |
然而 |
未必 |
不见得 |
df = pd.read_csv('./data/test.txt',sep='\s+',header=None)
df
|
0 |
1 |
2 |
0 |
你好 |
我好 |
他也好 |
1 |
也许 |
大概 |
有可能 |
2 |
然而 |
未必 |
不见得 |
df.columns = ['a','b','c']
df
|
a |
b |
c |
0 |
你好 |
我好 |
他也好 |
1 |
也许 |
大概 |
有可能 |
2 |
然而 |
未必 |
不见得 |
df.rename(index={0:'a1',1:'a2',2:'a3'})
|
a |
b |
c |
a1 |
你好 |
我好 |
他也好 |
a2 |
也许 |
大概 |
有可能 |
a3 |
然而 |
未必 |
不见得 |
df = pd.read_csv('./data/test.txt',sep='\s+',header=None,names=['A','B','C'])
df
|
A |
B |
C |
0 |
你好 |
我好 |
他也好 |
1 |
也许 |
大概 |
有可能 |
2 |
然而 |
未必 |
不见得 |
透视表
df = pd.read_csv('./data/透视表-篮球赛.csv')
df.head()
|
对手 |
胜负 |
主客场 |
命中 |
投篮数 |
投篮命中率 |
3分命中率 |
篮板 |
助攻 |
得分 |
0 |
勇士 |
胜 |
客 |
10 |
23 |
0.435 |
0.444 |
6 |
11 |
27 |
1 |
国王 |
胜 |
客 |
8 |
21 |
0.381 |
0.286 |
3 |
9 |
27 |
2 |
小牛 |
胜 |
主 |
10 |
19 |
0.526 |
0.462 |
3 |
7 |
29 |
3 |
灰熊 |
负 |
主 |
8 |
20 |
0.400 |
0.250 |
5 |
8 |
22 |
4 |
76人 |
胜 |
客 |
10 |
20 |
0.500 |
0.250 |
3 |
13 |
27 |
pivot_table有四个最重要的参数index、values、columns、aggfunc
- index参数:分类汇总的分类条件
- 每个pivot_table必须拥有一个index。如果想查看哈登对阵每个队伍的得分则需要对每一个队进行分类并计算其各类得分的平均值:
df.pivot_table(index='胜负')
|
3分命中率 |
助攻 |
命中 |
得分 |
投篮命中率 |
投篮数 |
篮板 |
胜负 |
|
|
|
|
|
|
|
胜 |
0.42819 |
9.666667 |
10.238095 |
32.952381 |
0.481524 |
21.142857 |
5.142857 |
负 |
0.29350 |
8.500000 |
7.500000 |
27.250000 |
0.354250 |
21.250000 |
4.750000 |
- 想看看哈登对阵同一对手在不同主客场下的数据,分类条件为对手和主客场
df.pivot_table(index=['对手','主客场'])
|
|
3分命中率 |
助攻 |
命中 |
得分 |
投篮命中率 |
投篮数 |
篮板 |
对手 |
主客场 |
|
|
|
|
|
|
|
76人 |
主 |
0.4290 |
7.0 |
8.0 |
29.0 |
0.381 |
21.0 |
4.0 |
客 |
0.2500 |
13.0 |
10.0 |
27.0 |
0.500 |
20.0 |
3.0 |
勇士 |
客 |
0.4440 |
11.0 |
10.0 |
27.0 |
0.435 |
23.0 |
6.0 |
国王 |
客 |
0.2860 |
9.0 |
8.0 |
27.0 |
0.381 |
21.0 |
3.0 |
太阳 |
客 |
0.5450 |
7.0 |
12.0 |
48.0 |
0.545 |
22.0 |
2.0 |
小牛 |
主 |
0.4620 |
7.0 |
10.0 |
29.0 |
0.526 |
19.0 |
3.0 |
尼克斯 |
主 |
0.3850 |
10.0 |
12.0 |
37.0 |
0.444 |
27.0 |
2.0 |
客 |
0.3530 |
9.0 |
9.0 |
31.0 |
0.391 |
23.0 |
5.0 |
开拓者 |
客 |
0.5710 |
3.0 |
16.0 |
48.0 |
0.552 |
29.0 |
8.0 |
掘金 |
主 |
0.1430 |
9.0 |
6.0 |
21.0 |
0.375 |
16.0 |
8.0 |
步行者 |
主 |
0.3330 |
10.0 |
8.0 |
29.0 |
0.364 |
22.0 |
8.0 |
客 |
0.2500 |
15.0 |
9.0 |
26.0 |
0.429 |
21.0 |
5.0 |
湖人 |
客 |
0.4440 |
9.0 |
13.0 |
36.0 |
0.591 |
22.0 |
4.0 |
灰熊 |
主 |
0.3395 |
8.0 |
9.5 |
30.0 |
0.420 |
22.5 |
4.5 |
客 |
0.3610 |
7.5 |
7.5 |
24.5 |
0.383 |
19.5 |
4.5 |
爵士 |
主 |
0.8750 |
13.0 |
19.0 |
56.0 |
0.760 |
25.0 |
2.0 |
客 |
0.3330 |
3.0 |
8.0 |
29.0 |
0.421 |
19.0 |
5.0 |
猛龙 |
主 |
0.2730 |
11.0 |
8.0 |
38.0 |
0.320 |
25.0 |
6.0 |
篮网 |
主 |
0.6150 |
8.0 |
13.0 |
37.0 |
0.650 |
20.0 |
10.0 |
老鹰 |
客 |
0.5450 |
11.0 |
8.0 |
29.0 |
0.533 |
15.0 |
3.0 |
骑士 |
主 |
0.4290 |
13.0 |
8.0 |
35.0 |
0.381 |
21.0 |
11.0 |
鹈鹕 |
主 |
0.4000 |
17.0 |
8.0 |
26.0 |
0.500 |
16.0 |
1.0 |
黄蜂 |
客 |
0.4000 |
11.0 |
8.0 |
27.0 |
0.444 |
18.0 |
10.0 |
- values参数:需要对计算的数据进行筛选
- 如果我们只需要哈登在主客场和不同胜负情况下的得分、篮板与助攻三项数据:
df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'])
|
|
助攻 |
得分 |
篮板 |
主客场 |
胜负 |
|
|
|
主 |
胜 |
10.555556 |
34.222222 |
5.444444 |
负 |
8.666667 |
29.666667 |
5.000000 |
客 |
胜 |
9.000000 |
32.000000 |
4.916667 |
负 |
8.000000 |
20.000000 |
4.000000 |
df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'],aggfunc='sum')
|
|
助攻 |
得分 |
篮板 |
主客场 |
胜负 |
|
|
|
主 |
胜 |
95 |
308 |
49 |
负 |
26 |
89 |
15 |
客 |
胜 |
108 |
384 |
59 |
负 |
8 |
20 |
4 |
df.pivot_table(index=['主客场','胜负'],aggfunc={'得分':'sum','篮板':'mean','助攻':'min'})
|
|
助攻 |
得分 |
篮板 |
主客场 |
胜负 |
|
|
|
主 |
胜 |
7 |
308 |
5.444444 |
负 |
7 |
89 |
5.000000 |
客 |
胜 |
3 |
384 |
4.916667 |
负 |
8 |
20 |
4.000000 |
df.pivot_table(index='主客场',values='得分',aggfunc='sum')
df.pivot_table(index='主客场',values='得分',aggfunc='sum',columns='对手',fill_value=0)
对手 |
76人 |
勇士 |
国王 |
太阳 |
小牛 |
尼克斯 |
开拓者 |
掘金 |
步行者 |
湖人 |
灰熊 |
爵士 |
猛龙 |
篮网 |
老鹰 |
骑士 |
鹈鹕 |
黄蜂 |
主客场 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
主 |
29 |
0 |
0 |
0 |
29 |
37 |
0 |
21 |
29 |
0 |
60 |
56 |
38 |
37 |
0 |
35 |
26 |
0 |
客 |
27 |
27 |
27 |
48 |
0 |
31 |
48 |
0 |
26 |
36 |
49 |
29 |
0 |
0 |
29 |
0 |
0 |
27 |
交叉表
- 是一种用于计算分组的特殊透视图,对数据进行汇总
- pd.crosstab(index,colums)
- index:分组数据,交叉表的行索引
- columns:交叉表的列索引
import pandas as pd
from pandas import DataFrame
df = DataFrame({'sex':['man','man','women','women','man','women','man','women','women'],
'age':[15,23,25,17,35,57,24,31,22],
'smoke':[True,False,False,True,True,False,False,True,False],
'height':[168,179,181,166,173,178,188,190,160]})
df
|
sex |
age |
smoke |
height |
0 |
man |
15 |
True |
168 |
1 |
man |
23 |
False |
179 |
2 |
women |
25 |
False |
181 |
3 |
women |
17 |
True |
166 |
4 |
man |
35 |
True |
173 |
5 |
women |
57 |
False |
178 |
6 |
man |
24 |
False |
188 |
7 |
women |
31 |
True |
190 |
8 |
women |
22 |
False |
160 |
df.groupby(by='sex')['smoke'].sum()
df.pivot_table(index='sex',values='smoke',aggfunc='sum')
pd.crosstab(df.smoke,df.sex)
sex |
man |
women |
smoke |
|
|
False |
2 |
3 |
True |
2 |
2 |
pd.crosstab(df.sex,df.smoke)
smoke |
False |
True |
sex |
|
|
man |
2 |
2 |
women |
3 |
2 |
pd.crosstab(df.smoke,df.age)
age |
15 |
17 |
22 |
23 |
24 |
25 |
31 |
35 |
57 |
smoke |
|
|
|
|
|
|
|
|
|
False |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
True |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |