Pandas中的一些高级操作

Pandas中的一些高级操作

1
2
3
import numpy as np
import pandas as pd
from pandas import DataFrame

替换操作

  • 替换操作可以同步作用于Series和DataFrame中
  • 单值替换
    • 普通替换:替换所有符合要求的元素:to_replace=15,value=’e’
    • 按列指定单值替换:to_replace={列标签:替换值},value=’value’
  • 多值替换
    • 列表替换:to_replace=[],value=[]
    • 字典替换(推荐):to_replace={to_replace:value,to_replace:value}
1
2
df = DataFrame(data=np.random.randint(0,100,size=(5,6)))
print(df)
    0   1   2   3   4   5
0  15  45   9   1   2  48
1  47  74  68  90  84   4
2  41  30  14  26  22  27
3   4  64  46  20   8  63
4  48  80  95  58   0  90
1
df.replace(to_replace=2,value='Two')    # 对指定元素进行替换

0 1 2 3 4 5
0 15 45 9 1 Two 48
1 47 74 68 90 84 4
2 41 30 14 26 22 27
3 4 64 46 20 8 63
4 48 80 95 58 0 90
1
df.replace(to_replace={1:'One'})    # 使用字典形式做替换

0 1 2 3 4 5
0 15 45 9 One 2 48
1 47 74 68 90 84 4
2 41 30 14 26 22 27
3 4 64 46 20 8 63
4 48 80 95 58 0 90
1
2
3
# 将指定列的元素进行替换:to_replace={列索引:被替换的值},value='value'
print(df.replace(to_replace={5:4},value='Four')) # 将第5列的4替换为‘Four’
df.replace(to_replace={0:4},value='Four') # 将第0列的4替换为‘Four’
    0   1   2   3   4     5
0  15  45   9   1   2    48
1  47  74  68  90  84  Four
2  41  30  14  26  22    27
3   4  64  46  20   8    63
4  48  80  95  58   0    90

0 1 2 3 4 5
0 15 45 9 1 2 48
1 47 74 68 90 84 4
2 41 30 14 26 22 27
3 Four 64 46 20 8 63
4 48 80 95 58 0 90

映射操作

  • 概念:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定(给一个元素值提供不同的表现形式)
  • 创建一个df,两列分别是姓名和薪资,然后给其名字起对应的英文名
1
2
3
4
5
6
dic = {
'name':['张三','李四','张三'],
'salary':[15000,20000,15000]
}
df = DataFrame(data=dic)
df

name salary
0 张三 15000
1 李四 20000
2 张三 15000
1
2
3
4
5
6
7
8
# 映射关系表
dic = {
'张三':'Tom',
'李四':'Jack'
}
print(df['name'].map(dic)) # map()属于Series的映射函数只能通过Series去调
df['e_name'] = df['name'].map(dic)
df
0     Tom
1    Jack
2     Tom
Name: name, dtype: object

name salary e_name
0 张三 15000 Tom
1 李四 20000 Jack
2 张三 15000 Tom

运算工具

  • 超过3000部分的钱缴纳50%的税,计算每个人的税后薪资
1
2
3
4
def after_sal(s):   #计算s对应的税后薪资
return s - (s-3000)*0.5
df['after_sal'] = df['salary'].map(after_sal) # 可以将df['salary']这个Series中每一个元素(薪资)作为参数传递给s
df

name salary e_name after_sal
0 张三 15000 Tom 9000.0
1 李四 20000 Jack 11500.0
2 张三 15000 Tom 9000.0
1
2
3
## 排序实现的随机抽样
- take()
- np.random.permutation()
1
2
df = DataFrame(data=np.random.randint(0,100,size=(100,3)),columns=['A','B','C'])
df

A B C
0 55 52 52
1 95 33 80
2 31 72 31
3 49 79 65
4 53 88 23
... ... ... ...
95 38 30 99
96 83 47 98
97 61 37 37
98 51 97 48
99 61 92 7

100 rows × 3 columns

1
2
# 生成乱序的随机序列
np.random.permutation(10) # 生成0-9的乱序随机序列
1
2
3
# 将原始数据打乱
print(df.take([2,0,1],axis=1)) # take与drop类似,0表示行,1表示列。并且take不能使用显示索引,只能使用“0,1,2...”隐式索引
df.take(np.random.permutation(3),axis=1) # 将np.random.permutation()函数引入,按列打乱
     C   A   B
0   52  55  52
1   80  95  33
2   31  31  72
3   65  49  79
4   23  53  88
..  ..  ..  ..
95  99  38  30
96  98  83  47
97  37  61  37
98  48  51  97
99   7  61  92

[100 rows x 3 columns]

C B A
0 52 52 55
1 80 33 95
2 31 72 31
3 65 79 49
4 23 88 53
... ... ... ...
95 99 30 38
96 98 47 83
97 37 37 61
98 48 97 51
99 7 92 61

100 rows × 3 columns

1
df.take(np.random.permutation(3),axis=1).take(np.random.permutation(100),axis=0)    # 行列全部打乱

C A B
25 54 23 65
78 56 89 46
13 19 83 61
21 46 25 65
68 5 41 2
... ... ... ...
62 4 84 77
98 48 51 97
28 92 78 51
43 60 67 41
19 90 45 90

100 rows × 3 columns

1
df.take(np.random.permutation(3),axis=1).take(np.random.permutation(100),axis=0)[0:50]  # 取前50行

B C A
5 97 33 69
7 38 89 26
54 86 75 18
2 72 31 31
34 95 95 12
72 85 25 0
80 1 82 11
28 51 92 78
61 58 88 54
16 8 83 6
96 47 98 83
62 77 4 84
19 90 90 45
3 79 65 49
26 56 77 80
70 99 9 47
99 92 7 61
53 79 75 50
12 9 15 82
4 88 23 53
65 63 43 3
40 40 31 91
52 65 64 28
98 97 48 51
94 50 62 2
89 33 23 86
32 17 79 78
57 39 64 62
59 78 39 10
30 21 17 14
93 13 57 43
71 48 33 87
74 20 66 49
47 16 90 64
43 41 60 67
81 28 36 59
91 74 81 76
87 51 54 68
41 6 20 19
63 97 56 13
29 12 87 69
42 18 90 3
75 23 53 37
69 56 82 61
58 23 61 73
85 48 99 33
55 64 14 24
39 64 75 53
48 3 86 83
92 96 45 0

数据的分类处理

  • 数据分类处理的核心:
    • groupby()函数
    • groups属性查看分组情况
1
2
3
4
5
6
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
1
2
# 水果的种类进行分析
df.groupby(by='item') # 三个分组情况在该对象当中
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001DBA1507E48>
1
2
# 查看详细的分组情况
df.groupby(by='item').groups
{'Apple': [0, 5], 'Banana': [1, 3], 'Orange': [2, 4]}
  • 分组聚合
1
2
3
# 计算出每一种水果的平均价格
print(df.groupby('item').mean()) # 对所有数值型数据取了平均
df.groupby('item')['price'].mean() # 只选择价钱做平均
        price  weight
item                 
Apple    3.00      28
Banana   2.75      25
Orange   3.50      35





item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
1
2
# 计算每种颜色对应水果的平均重量
df.groupby('color')['weight'].mean()
color
green     31.333333
red       12.000000
yellow    35.000000
Name: weight, dtype: float64
1
2
3
4
5
dic = df.groupby('color')['weight'].mean().to_dict()
# 将计算出的平均重量汇总到源数据
print(df['color'].map(dic)) # 此处使用映射将所有颜色对应的数值填充满
df['mean_w'] = df['color'].map(dic)
df
0    12.000000
1    35.000000
2    35.000000
3    31.333333
4    31.333333
5    31.333333
Name: color, dtype: float64

item price color weight mean_w
0 Apple 4.0 red 12 12.000000
1 Banana 3.0 yellow 20 35.000000
2 Orange 3.0 yellow 50 35.000000
3 Banana 2.5 green 30 31.333333
4 Orange 4.0 green 20 31.333333
5 Apple 2.0 green 44 31.333333

高级数据聚合

  • 使用groupby()分组后,也可以使用transform和apply提供自定义函数实现更多的运算
  • df.groupby(‘item’)[‘price’].sum() <==> df.groupby(‘item’)[‘price’].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
1
2
3
4
5
6
def my_mean(s):
m_sum = 0
for i in s:
m_sum += i
return m_sum / len(s)
df.groupby('item')['price'].transform(my_mean) # transform返回的经过映射的结果
0    3.00
1    2.75
2    3.50
3    2.75
4    3.50
5    3.00
Name: price, dtype: float64
1
df.groupby('item')['price'].apply(my_mean)  # apply返回的没有经过映射
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64

数据加载

  • 读取type-.txt文件数据
1
2
df = pd.read_csv('./data/type-.txt')
df # 可以看到此处将文件内容当成了索引

你好-我好-他也好
0 也许-大概-有可能
1 然而-未必-不见得
1
2
3
4
df = pd.read_csv('./data/type-.txt',header=None)
print(df) # 通过header=None读取文件没有索引
df = pd.read_csv('./data/type-.txt',header=None,sep='-')
df # sep为指定分隔符,借此将数据拆分
           0
0  你好-我好-他也好
1  也许-大概-有可能
2  然而-未必-不见得

0 1 2
0 你好 我好 他也好
1 也许 大概 有可能
2 然而 未必 不见得
  • 读取数据库中的数据
1
2
3
# 连接数据库,获取连接对象
import sqlite3 as sqlite3
conn = sqlite3.connect('./data/weather_2012.sqlite')
1
2
3
# 读取库表中的数据值
sql_df = pd.read_sql('select * from weather_2012', conn)
sql_df

index Date/Time Temp (C) Dew Point Temp (C) Rel Hum (%) Wind Spd (km/h) Visibility (km) Stn Press (kPa) Weather
0 0.0 2012-01-01 00:00:00 -1.8 -3.9 86.0 4.0 8.0 101.24 Fog
1 1.0 2012-01-01 01:00:00 -1.8 -3.7 87.0 4.0 8.0 101.24 Fog
2 2.0 2012-01-01 02:00:00 -1.8 -3.4 89.0 7.0 4.0 101.26 Freezing Drizzle,Fog
3 3.0 2012-01-01 03:00:00 -1.5 -3.2 88.0 6.0 4.0 101.27 Freezing Drizzle,Fog
4 4.0 2012-01-01 04:00:00 -1.5 -3.3 88.0 7.0 4.8 101.23 Fog
... ... ... ... ... ... ... ... ... ...
8781 8781.0 2012-12-31 21:00:00 -0.5 -1.5 93.0 28.0 4.8 99.95 Snow
8782 8782.0 2012-12-31 22:00:00 -0.2 -1.8 89.0 28.0 9.7 99.91 Snow
8783 8783.0 2012-12-31 23:00:00 0.0 -2.1 86.0 30.0 11.3 99.89 Snow
8784 NaN None NaN NaN NaN NaN NaN NaN Fog
8785 NaN None NaN NaN NaN NaN NaN NaN Fog

8786 rows × 9 columns

1
2
3
4
# 将一个df中的数据值写入存储到db
df.to_sql('sql_data666', conn)
sql_df = pd.read_sql('select * from sql_data666', conn)
sql_df # 写入数据库后进行读取,读取成功

index 0 1 2
0 0 你好 我好 他也好
1 1 也许 大概 有可能
2 2 然而 未必 不见得

透视表

  • 透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot_table。
  • 透视表的优点:
    • 灵活性高,可以随意定制你的分析计算要求
    • 脉络清晰易于理解数据
    • 操作性强,报表神器
1
2
df = pd.read_csv('./data/透视表-篮球赛.csv',encoding='utf8')
df

对手 胜负 主客场 命中 投篮数 投篮命中率 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
5 黄蜂 胜 客 8 18 0.444 0.400 10 11 27
6 灰熊 负 客 6 19 0.316 0.222 4 8 20
7 76人 负 主 8 21 0.381 0.429 4 7 29
8 尼克斯 胜 客 9 23 0.391 0.353 5 9 31
9 老鹰 胜 客 8 15 0.533 0.545 3 11 29
10 爵士 胜 主 19 25 0.760 0.875 2 13 56
11 骑士 胜 主 8 21 0.381 0.429 11 13 35
12 灰熊 胜 主 11 25 0.440 0.429 4 8 38
13 步行者 胜 客 9 21 0.429 0.250 5 15 26
14 猛龙 负 主 8 25 0.320 0.273 6 11 38
15 太阳 胜 客 12 22 0.545 0.545 2 7 48
16 灰熊 胜 客 9 20 0.450 0.500 5 7 29
17 掘金 胜 主 6 16 0.375 0.143 8 9 21
18 尼克斯 胜 主 12 27 0.444 0.385 2 10 37
19 篮网 胜 主 13 20 0.650 0.615 10 8 37
20 步行者 胜 主 8 22 0.364 0.333 8 10 29
21 湖人 胜 客 13 22 0.591 0.444 4 9 36
22 爵士 胜 客 8 19 0.421 0.333 5 3 29
23 开拓者 胜 客 16 29 0.552 0.571 8 3 48
24 鹈鹕 胜 主 8 16 0.500 0.400 1 17 26

pivot_table有四个最重要的参数index、values、columns、aggfunc

  • index参数:分类汇总的分类条件
    • 每个pivot_table必须拥有一个index。如果想查看哈登对阵每个队伍的得分则需要对每一个队进行分类并计算其各类得分的平均值
  • 想看哈登对阵同一对手在不同主客场下的数据,分类条件为对手和主客场
1
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参数:需要对计算的数据进行筛选
    • 如果我们只需要哈登在主客场和不同胜负情况下的得分、篮板与助攻三项数据:
1
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
  • Aggfunc参数:设置我们对数据聚合时进行的函数操作
    • 当我们未设置aggfunc时,它默认aggfunc=’mean’计算均值。
  • 还想获得james harden在主客场和不同胜负情况下的总得分、总篮板、总助攻时:
1
df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'],aggfunc='sum')

助攻 得分 篮板
主客场 胜负
主 胜 95 308 49
负 26 89 15
客 胜 108 384 59
负 8 20 4
  • Columns:可以设置列层次字段
    • 对values字段进行分类
1
2
# 获取所有队主客场的总得分
df.pivot_table(index=['主客场'],values=['得分'],aggfunc='sum')

得分
主客场
主 397
客 404
1
2
# 获取每个队主客场的总得分(在总得分的基础上又进行了对手的分类)
df.pivot_table(index=['主客场'],values=['得分'],columns='对手',aggfunc='sum',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,columns)
    • index:分组数据,交叉表的行索引
    • columns:交叉表的列索引
1
2
3
4
5
6
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
  • 求出各个性别抽烟的人数
1
pd.crosstab(df.smoke,df.sex)

sex man women
smoke
False 2 3
True 2 2
  • 求出各个年龄段抽烟人情况
1
pd.crosstab(df.age,df.smoke)

smoke False True
age
15 0 1
17 0 1
22 1 0
23 1 0
24 1 0
25 1 0
31 0 1
35 0 1
57 1 0

本文提及的数据集下载地址:
链接:https://pan.baidu.com/s/1lhAiSXBw47MK9QdqwA05Lg
提取码:1111


Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2019-2022 Woody
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信