【任务四】显卡日志
下面给出了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 | 1.130 |
model_2 | 0.360 | 0.794 | 0.011 | 1.083 | 1.137 | 0.394 |
… | … | … | … | … | … | … |
【解答】
import numpy as np
import pandas as pd
df=pd.read_table('benchmark.txt', header=None)
# 取出Benchmarking #2# #4# precision type #1# 中的 2,4,1
pat1='Benchmarking (\w+) (\w+) precision type (\w+)'
name1 = ['type1','pricision','model1']
df1=df[0].str.extract(pat1).rename(columns=dict(zip(range(3),name1))).dropna().reset_index(drop=True)
# 取出#1# model average #2# time : #3# ms 中的1,2,3
pat2='(\w+)\s*model average (\w+).+:\s*(\d+\.\d+)'
name2=['model2','type2','time']
df2=df[0].str.extract(pat2).rename(columns=dict(zip(range(3),name2))).dropna().reset_index(drop=True)
# 转换成float类型,这里也可以转换成numpy用around函数处理,numpy.around(a, n)
df2['time_val']=pd.to_numeric(df2.time.str[:6])
# 这里要把两个表链接起来!但是merge用不了因为key不唯一,而且type1和type2有部分是不一样的,所以使用concat直接左右拼接
res=pd.concat([df1,df2],axis=1).pivot(index=['model2','type2'],columns='pricision',
values='time_val').unstack(1)
res.columns=res.columns.map(lambda x :x[1]+'_'+x[0])
res=res.sort_index(axis=1,ascending=False)
res
【任务五】水压站点的特征工程
df1
和df2
中分别给出了18年和19年各个站点的数据,其中列中的H0
至H23
分别代表当天0
点至23
点;df3
中记录了18-19年的每日该地区的天气情况,请完成如下的任务:
import pandas as pd
import numpy as np
df1 = pd.read_csv('yali18.csv')
df2 = pd.read_csv('yali19.csv')
df3 = pd.read_csv('qx1819.csv')
1.通过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
2.在上一问构造的df
基础上,构造下面的特征序列或DataFrame
,并把它们逐个拼接到df
的右侧
- 当天最高温、最低温和它们的温差
- 当天是否有沙暴、是否有雾、是否有雨、是否有雪、是否为晴天
- 选择一种合适的方法度量雨量/下雪量的大小(构造两个序列分别表示二者大小)
- 限制只用4列,对风向进行
0-1
编码(只考虑风向,不考虑大小)
3.对df
的水压一列构造如下时序特征:
- 当前时刻该站点水压与本月的相同整点时间该站点水压均值的差,例如当前时刻为
2018-05-20 17:00:00
,那么对应需要减去的值为当前月所有17:00:00
时间点水压值的均值 - 当前时刻所在周的周末该站点水压均值与工作日水压均值之差
- 当前时刻向前7日内,该站点水压的均值、标准差、
0.95
分位数、下雨天数与下雪天数的总和 - 当前时刻向前7日内,该站点同一整点时间水压的均值、标准差、
0.95
分位数 - 当前时刻所在日的该站点水压最高值与最低值出现时刻的时间差
【解答】
# 第一小问
df1['站点']=df1.MeasName.str[2:].astype('int')
res1=pd.wide_to_long(df1,stubnames='H',i=['Time','MeasName','站点'],j='时间')
res1=res1.reset_index()
res1['时间']=pd.to_timedelta(res1['时间'].astype(str)+':00:00')
res1['Time']=pd.to_datetime(res1['Time'])
res1['time']=res1['时间'] + res1['Time']
res1=res1.drop(['时间','MeasName'],axis=1).sort_values(['time',
'站点']).set_index('time').rename(columns={'H':'压力'})
df2['站点']=df2.MeasName.str[2:].astype('int')
res2=pd.wide_to_long(df2,stubnames='H',i=['Time','MeasName','站点'],j='时间')
res2=res2.reset_index()
res2['时间']=pd.to_timedelta(res2['时间'].astype(str)+':00:00')
res2['Time']=pd.to_datetime(res2['Time'])
res2['time']=res2['时间'] + res2['Time']
res2=res2.drop(['时间','MeasName'],axis=1).sort_values(['time',
'站点']).set_index('time').rename(columns={'H':'压力'})
res=pd.concat([res1,res2])
res1=res.drop('Time',1)
res1
主要思路就是利用str的可加性!
# 匹配最高温和最低温,这里我用的\d*是因为有两个数据只有一个温度,这里我按删除处理
pat1=r'(\-?\d+)[C℃]\s*~\s*(\-?\d+).+'
df_1=df3['气温'].str.extract(pat1)
df_1=df_1.dropna().astype('int').rename(columns=dict(zip(range(2),['最高温','最低温'])))
df_2=pd.concat([df_1,df3['日期']],axis=1)
# 行索引408是左边小于右边的,所以交换两者的值
df_2.loc[408,'最高温'],df_2.loc[408,'最低温']=df_2.loc[408,'最低温'],df_2.loc[408,'最高温']
df_2['温差']=df_2['最高温']-df_2['最低温']
# 去重
#df3.dropna(inplace=True)
# merge合并
res2_2=res.reset_index().merge(df_2,left_on='Time',right_on='日期',how='left').drop('日期',1).set_index('time')
res2_2
df3['日期']=pd.to_datetime(df3['日期'])
pat2='([雪沙雾雨晴])'
df2_3=pd.concat([pd.get_dummies(df3['天气'].str.extract(pat2).fillna('其他')).drop('0_其他',
1).rename(columns=dict(zip(['0_晴','0_沙','0_雨',
'0_雪','0_雾'],['是否晴天','是否沙暴','是否雨天','是否雪天','是否雾天']))),df3['日期']],axis=1)
# 合并
res2_3=res2_2.reset_index().merge(df2_3,left_on='Time',right_on='日期',how='left').drop('日期',1).set_index('time')
res2_3
df2_4=df3['天气'].str.extract('([大中小])')+df3['天气'].str.extract('([雨])')
df2_4.fillna('无雨',inplace=True)
df2_5=df3['天气'].str.extract('([大中小])')+df3['天气'].str.extract('([雪])')
df2_5.fillna('无雪',inplace=True)
# 变成有序列表后直接转成 0 1 2 3 代表三种降雪量/降雨量
s1=df2_4[0].astype('category').cat.reorder_categories(['无雨','小雨','中雨','大雨'],ordered=True).cat.codes
s2=df2_5[0].astype('category').cat.reorder_categories(['无雪','小雪','中雪','大雪'],ordered=True).cat.codes
df2_6=pd.concat((s1.to_frame().rename(columns={0:'降雨量'}),s2.to_frame().rename(columns={0:'降雪量'})),axis=1)
df2_7=pd.concat([df2_6,df3['日期']],axis=1)
res2_4=res2_3.reset_index().merge(df2_7,left_on='Time',right_on='日期',how='left').drop('日期',1).set_index('time')
res2_4
# 利用str.contains函数,来判断有什么风向的风。然后转成int型就可以构造出0-1编码了
data1=df3['风向'].str.contains('东').to_frame().rename(columns={'风向':'东'}).astype('int')
data2=df3['风向'].str.contains('南').to_frame().rename(columns={'风向':'南'}).astype('int')
data3=df3['风向'].str.contains('西').to_frame().rename(columns={'风向':'西'}).astype('int')
data4=df3['风向'].str.contains('北').to_frame().rename(columns={'风向':'北'}).astype('int')
df25=pd.concat([data1,data2,data3,data4,df3['日期']],axis=1)
res2_5=res2_4.reset_index().merge(df25,left_on='Time',right_on='日期',how='left').drop('日期',1).set_index('time')
res2_5
# 去掉第二问中用于匹配的列 'Time',并且去掉缺失值
df=res2_5.drop('Time',axis=1).dropna()
# 根据题意根据年 月 时间 站点 分组,这里为了和df匹配,使用transform聚合。
s3_1=df.reset_index().groupby([df.reset_index().time.dt.year,
df.reset_index().time.dt.month,
df.reset_index().time.dt.hour,'站点'])['压力'].transform('mean')
s3_12=df.reset_index()['压力']-s3_1
df3_1=pd.concat([s3_12,df.reset_index().time],axis=1)
df['与本月均值差']=df3_1.set_index('time')
df
data3_1=df.reset_index()[df.reset_index().time.dt.dayofweek.isin(range(5)).values]
res1=data3_1.groupby([data3_1.time.dt.year,data3_1.time.dt.isocalendar().week,'站点'])['压力'].mean()
data3_2=df.reset_index()[df.reset_index().time.dt.dayofweek.isin([5,6]).values]
res2=data3_2.groupby([data3_2.time.dt.year,data3_2.time.dt.isocalendar().week,'站点'])['压力'].mean()
res3_2=res2-res1
res3_2=res3_2.to_frame().rename_axis(index={'time':'年份','week':'周'}).rename(columns={'压力':'周末与工作日水压差'})
df_['年份']=df_.time.dt.year
df_['周']=df_.time.dt.isocalendar().week
data3_2=df_.merge(res3_2,on=['年份','周','站点'])
data3_2[['time','周末与工作日水压差']].set_index('time')
# 利用apply函数对每个站点进行操作
s11=df_.groupby(['站点'])[['time','压力']].apply(lambda x : x.set_index('time').rolling('7D').mean()).rename(columns={'压力':'七日平均压力'})
s22=df_.groupby(['站点'])[['time','压力']].apply(lambda x : x.set_index('time').rolling('7D').std()).rename(columns={'压力':'七日压力标准差'})
s33=df_.groupby(['站点'])[['time','压力']].apply(lambda x : x.set_index('time').rolling('7D').quantile(0.95)).rename(columns={'压力':'七日压力0.95分位数'})
res3_3=pd.concat([s11,s22,s33],axis=1).reset_index()
res3_3['日期']=pd.to_datetime(res3_3.time.dt.date)
# 是否下雨和下雪的天数 利用前面的df2_3
df3_3=df2_3[['日期','是否雨天','是否雪天']].set_index('日期').rolling('7D').sum().reset_index()
# 与上面的拼起来
result3_3=res3_3.merge(df3_3,on='日期').rename(columns={'是否雨天':'七日下雨天','是否雪天':'七日下雪天'}).set_index('time')
result3_3
s111=df_.groupby(['站点',df_.time.dt.hour])[['time','压力']].apply(lambda x : x.set_index(
'time').rolling('7D').mean()).rename(columns={'压力':'七日同一整点时间平均压力'})
s222=df_.groupby(['站点',df_.time.dt.hour])[['time','压力']].apply(lambda x : x.set_index(
'time').rolling('7D').std()).rename(columns={'压力':'七日同一整点时间压力标准差'})
s333=df_.groupby(['站点',df_.time.dt.hour])[['time','压力']].apply(lambda x : x.set_index(
'time').rolling('7D').quantile(0.95)).rename(columns={'压力':'七日同一整点压力0.95分位数'})
res3_4=pd.concat([s111,s222,s333],axis=1)
# 可以看下与上一问的区别
result3_4=res3_4.droplevel(1).reset_index().sort_values(['站点','time']).set_index('time')
result3_4
s3_5=df_.groupby(['站点',df_.time.dt.year.rename('year'),df_.time.dt.month.rename(
'month'),df_.time.dt.day.rename('day')])[['time'
,'压力']].apply(lambda x : abs(x['压力'].argmax()-x['压力'].argmin()) )
s3_5=s3_5.reset_index('站点')
s3_5.index=s3_5.index.map(lambda x : str(x[0])+'-'+str(x[1])+'-'+str(x[2]))
s3_5=s3_5.reset_index()
s3_5['日期']=pd.to_datetime(s3_5['index'])
s3_5.drop('index',1).rename(columns={0:'时间差'})
result3_5=result3_3[['日期','站点']].reset_index().merge(s3_5.drop(
'index',1).rename(columns={0:'时间差'}),on=['日期','站点']).set_index('time').drop('日期',1)
result3_5
第三小问就是合理利用apply !! 以后再回来操作一遍这些!!