Pandas进阶之综合练习
pandas进阶系列根据datawhale远昊大佬的joyful pandas教程写一些自己的心得和补充,本文题目源自datawhale远昊大佬,本篇博客是其中任务四、任务五的解答,任务一至三的解答可以看我的另一篇博客
【任务四】显卡日志
下面给出了3090显卡的性能测评日志结果,每一条日志有如下结构:
Benchmarking #2# #4# precision type #1#
#1# model average #2# time : #3# ms
其中#1#代表的是模型名称,#2#的值为train(ing)或inference,表示训练状态或推断状态,#3#表示耗时,#4#表示精度,其中包含了float, half, double三种类型,下面是一个具体的例子:
Benchmarking Inference float precision type resnet50
resnet50 model average inference time : 13.426570892333984 ms
请把日志结果进行整理,变换成如下状态,model_i用相应模型名称填充,按照字母顺序排序,数值保留三位小数:
Train_half | Train_float | Train_double | Inference_half | Inference_float | Inference_double |
---|---|---|---|---|---|
model_1 | 0.954 | 0.901 | 0.357 | 0.281 | 0.978 |
model_2 | 0.360 | 0.794 | 0.011 | 1.083 | 1.137 |
… | … | … | … | … | … |
【数据下载】链接:https://pan.baidu.com/s/1CjfdtavEywHtZeWSmCGv3A 提取码:4mui
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
我的思路
先把数据预处理一下,这里直接用了python的文件操作新生成了一份文件,把原文件中要用到的日志信息合并到了一行(由于每两行对应一条log信息,所以我将所有第一行的末尾的换行符删除替换为空格符,并生成新文件,用pandas读取新文件
with open('../data/benchmark.txt', 'r') as f:
l = f.readlines()
data = l[10:-2]
for i in range(0,len(data),2):
data[i] = data[i][:-1] + ' '
with open('../data/benchmark.data', 'a+') as out:
for line in data:
out.write(line)
生成后的文件是用空格分隔的,所以使用pandas载入文件时自定义一下分隔符
df = pd.read_table('../data/benchmark.data', sep=' ', header=None)
df.head(3)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Benchmarking | Training | float | precision | type | mnasnet0_5 | mnasnet0_5 | NaN | model | average | train | time | : | NaN | 28.527637 | ms |
1 | Benchmarking | Training | float | precision | type | mnasnet0_75 | mnasnet0_75 | NaN | model | average | train | time | : | NaN | 34.105487 | ms |
2 | Benchmarking | Training | float | precision | type | mnasnet1_0 | mnasnet1_0 | NaN | model | average | train | time | : | NaN | 34.313774 | ms |
取出需要用到的列:包括精度类型、模型名称、训练/推断状态和时间
df = df[[2,5,10,14]]
df.head(3)
2 | 5 | 10 | 14 | |
---|---|---|---|---|
0 | float | mnasnet0_5 | train | 28.527637 |
1 | float | mnasnet0_75 | train | 34.105487 |
2 | float | mnasnet1_0 | train | 34.313774 |
df.columns = ['type', 'name', 'status', 'time']
df.head(3)
type | name | status | time | |
---|---|---|---|---|
0 | float | mnasnet0_5 | train | 28.527637 |
1 | float | mnasnet0_75 | train | 34.105487 |
2 | float | mnasnet1_0 | train | 34.313774 |
df.isnull().sum().sum()
0
截止到这一步已经获取到了所要用到的数据,并且没有发现空数据,从上面的表和题目中所要求的表可以判断出,这道题是要把长表变成宽表,因此可以想到用pd.pivot
来处理,将模型名称作为索引,列包括状态和精度类型,矩阵的值都是时间,因此pivot的参数就出来了,在pivot之前先将时间保留到三位
df.time = df.time.astype('float').round(3)
res = pd.pivot(df, index='name',
columns=['status', 'type'],
values='time')
res.head(3)
status | train | inference | train | inference | train | inference |
---|---|---|---|---|---|---|
type | float | float | half | half | double | double |
name | ||||||
densenet121 | 93.357 | 15.637 | 88.976 | 19.772 | 417.207 | 144.111 |
densenet161 | 136.624 | 31.750 | 144.319 | 27.555 | 1290.287 | 511.177 |
densenet169 | 104.840 | 21.598 | 121.556 | 26.371 | 511.404 | 175.808 |
整体的分布已经正确了,只剩下列名不一致与列的顺序和索引的名称不一样了,都更改一下即可
cols = []
for a,b in res.columns:
cols.append(a+'_'+b)
res.columns = cols
res.rename_axis(index='', inplace=True)
res = res[['train_half','train_float','train_double','inference_half','inference_float','inference_double']]
res.head()
train_half | train_float | train_double | inference_half | inference_float | inference_double | |
---|---|---|---|---|---|---|
densenet121 | 88.976 | 93.357 | 417.207 | 19.772 | 15.637 | 144.111 |
densenet161 | 144.319 | 136.624 | 1290.287 | 27.555 | 31.750 | 511.177 |
densenet169 | 121.556 | 104.840 | 511.404 | 26.371 | 21.598 | 175.808 |
densenet201 | 118.940 | 129.334 | 654.365 | 33.394 | 26.169 | 223.960 |
mnasnet0_5 | 27.198 | 28.528 | 48.232 | 6.929 | 8.039 | 11.870 |
大功告成!
总结
我使用了python来预处理了文件,没有直接用pandas处理,不过我认为抓着耗子的就是好猫,所以只要结果是正确的,运行效率和写的效率够快就ok
【任务五】水压站点的特征工程
df1和df2中分别给出了18年和19年各个站点的数据,其中列中的H0至H23分别代表当天0点至23点;df3中记录了18-19年的每日该地区的天气情况,请完成如下的任务:
- 通过df1和df2构造df,把时间设为索引,第一列为站点编号,第二列为对应时刻的压力大小,排列方式如下(压力数值请用正确的值替换):
站点 压力
2018-01-01 00:00:00 1 1.0
2018-01-01 00:00:00 2 1.0
... ... ...
2018-01-01 00:00:00 30 1.0
2018-01-01 01:00:00 1 1.0
2018-01-01 01:00:00 2 1.0
... ... ...
2019-12-31 23:00:00 30 1.0
- 在上一问构造的df基础上,构造下面的特征序列或DataFrame,并把它们逐个拼接到df的右侧
- 当天最高温、最低温和它们的温差
- 当天是否有沙暴、是否有雾、是否有雨、是否有雪、是否为晴天
- 选择一种合适的方法度量雨量/下雪量的大小(构造两个序列分别表示二者大小)
- 限制只用4列,对风向进行0-1编码(只考虑风向,不考虑大小)
- 对df的水压一列构造如下时序特征:
- 当前时刻该站点水压与本月的相同整点时间该站点水压均值的差,例如当前时刻为2018-05-20 17:00:00,那么对应需要减去的值为当前月所有17:00:00时间点水压值的均值
- 当前时刻所在周的周末该站点水压均值与工作日水压均值之差
- 当前时刻向前7日内,该站点水压的均值、标准差、0.95分位数、下雨天数与下雪天数的总和
- 当前时刻向前7日内,该站点同一整点时间水压的均值、标准差、0.95分位数
- 当前时刻所在日的该站点水压最高值与最低值出现时刻的时间差
【数据下载】链接:https://pan.baidu.com/s/1Tqad4b7zN1HBbc-4t4xc6w 16 提取码:ijbd
import pandas as pd
import numpy as np
df1 = pd.read_csv('../data/yali18.csv')
df2 = pd.read_csv('../data/yali19.csv')
df3 = pd.read_csv('../data/qx1819.csv')
df1.head(2)
Time | MeasName | H0 | H1 | H2 | H3 | H4 | H5 | H6 | H7 | ... | H14 | H15 | H16 | H17 | H18 | H19 | H20 | H21 | H22 | H23 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2018-01-01 | 站点4 | 0.402750 | 0.407625 | 0.418125 | 0.425250 | 0.426 | 0.42525 | 0.417375 | 0.426375 | ... | 0.348750 | 0.35925 | 0.35550 | 0.34425 | 0.352125 | 0.35625 | 0.34725 | 0.343875 | 0.356625 | 0.418875 |