pandas-task11-综合练习.md

【任务一】显卡日志

下面给出了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用相应模型名称填充,按照字母顺序排序,数值保留三位小数:
在这里插入图片描述

解决思路

1.文本数据正则抽取,去缺失值,列重命名,重置index

根据数据特点,可以看出需要统计的数据都是一个格式,首先使用正则表达式抽取需要的第一行和第二行信息,并将抽取的信息重命名。这里也可以直接使用子组的命名达到重命名列的效果,下面演示的是第一种方法:

df=pd.read_table('data/benchmark.txt', header=None)
pat1='Benchmarking (\w+) (\w+) precision type (\w+)'
pat2='(\w+)  model average (\w+) time :  (.+) ms'
bench_info=df[0].str.extract(pat1).rename(columns={0:'type_x',
								 1:'precision',
								 2:'model_name_x'}).dropna()
								 .reset_index(drop=True)

使用子组的方法重命名列名:

df=pd.read_table('data/benchmark.txt', header=None)
pat1='Benchmarking (?P<type_x>\w+) (?P<precision>\w+) precision type (?P<model_name_x>\w+)'
pat2='(?P<model_name_y>\w+)  model average (?P<type_y>\w+) time :  (?P<time_val>.+) ms'
bench_info=df[0].str.extract(pat1).dropna()
				.reset_index(drop=True)
bench_info

下面是对应的第一行信息,去掉了缺失值,以及重置了index,命名为bench_info:
在这里插入图片描述
类似地可以得到每个模型地第二个行信心,同样处理,命名为model_info,可以看到这里获取地两个信息数量相同,是一一对应的:

model_info=df[0].str.extract(pat2).rename(
							columns={0:'model_name_y', 
							1:'type_y',2:'time_val'}).dropna()
							.reset_index(drop=True)

在这里插入图片描述

2.横向连接两表-concat

将两个表合并成一个表:

temp=pd.concat([bench_info,model_info],axis=1).reset_index(
												drop=True)
temp

在这里插入图片描述

注意这里不能用merge或者merge_table,merge是因为不唯一,merge_table用了的话会有很多重复数据。这里之前花了很多时间定位问题。

3.去除重复列,精度保留三位小数

temp=temp[['model_name_x','type_y','precision',
           'time_val']].rename(columns={'model_name_x':'model','type_y':'type'})
temp.time_val=pd.to_numeric(temp.time_val, 
                            errors='coerce').round(3)
temp

在这里插入图片描述

4.表的变型 长变宽pivot

长表变宽表,使用pivot

#变型 长变宽
temp=temp.pivot(index=['model','type'], 
			columns='precision', values='time_val')
temp

在这里插入图片描述

5.索引变型及多级索引的压缩

下面使用unstack,将最里面一层index进行行列转换:

temp=temp.unstack()
temp.head()

在这里插入图片描述

使用map函数对多级index进行组合变型:

temp.columns=temp.columns.map(lambda x:(x[1]+'_'+x[0]))
temp=temp.reset_index()
temp.head()

在这里插入图片描述

6.调整,按模型名称排序

最后进行行和列的重新排序以达到最好的显示效果,这里对列试了一下sort_index,但是model列会被放到中间,最终还是选择了最基础的方法。对行以模型名称按照字母顺序排序:

# temp.sort_index(axis=1,ascending=False)
temp=temp[['model','train_half','train_float',
           'train_double','inference_half',
           'inference_float','inference_double']]
temp=temp.sort_values('model',ascending=True)
temp.head()

在这里插入图片描述

【任务二】水压站点的特征工程

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

解决思路

原表样式 df2为19年水站数据,
df118年数据,与之类似:
在这里插入图片描述

1.表变型 宽表变长表-melt

#宽表变长表
H_list=['H'+str(i) for i in range(12)]
df1=df1.melt(id_vars =['Time','MeasName'],
             value_vars =H_list,var_name = 'H',
             value_name = '压力')
df1

在这里插入图片描述
这里后来检查的时候发现最终少了一半数据,定位问题发现是这里时间H0-H23一共24h,我给写成了12个小时,修改后:

#宽表变长表
H_list=['H'+str(i) for i in range(24)]
df1=df1.melt(id_vars =['Time','MeasName'],
             value_vars =H_list,var_name = 'H',
             value_name = '压力')
df1

在这里插入图片描述

2.修改格式-文本正则,时间格式化

# 修改对应格式 str正则
df1.MeasName=df1.MeasName.str.replace('站点','')
df1.H=df1.H.str.replace('H','')
df1.Time=df1.Time+'-'+df1.H
df1.Time=pd.to_datetime(df1.Time,format='%Y-%m-%d-%H')
df1=df1.rename(columns={'MeasName':'站点'}).drop(columns='H')
df1

在这里插入图片描述

3.设置时间为index

df1=df1.rename(columns={'Time':' '}).set_index(' ')
df1

在这里插入图片描述
df2按照完全一致的方式处理,处理后样式:
在这里插入图片描述

4.纵向合并两个表 concat

df=pd.concat([df1,df2],axis=0)
df

在这里插入图片描述

问题2:

表3为当天的天气情况:
在这里插入图片描述

  • 在上一问构造的df基础上,构造下面的特征序列或DataFrame,并把它们逐个拼接到df的右侧
    • 当天最高温、最低温和它们的温差

解决思路

1.取df的时间年月日构成date列

df['date']=df.index.astype('str').str[0:10]
df

在这里插入图片描述
这里数据应该是52万5千6百行,少一半的原因上面已经说了,是因为匹配的时候只匹配了H0-H11,之后的操作应该都没问题,所以就不改了。

2.正则表达式获取最高温和最低温

df3 = pd.read_csv('./data/qx1819.csv')
pat_temp='(.?\d+).{0,2}~\s{0,2}(.?\d+).?'
df3_temp=df3['气温'].str.extract(pat_temp).rename(columns={0:'最高温',1:'最低温'})
df3=pd.concat([df3,df3_temp],axis=1)
df3

在这里插入图片描述
这里可以使用isna()函数查看是否有没用匹配到的,可以用来检查正则规则是否合适,以及数据是否正常,这里我都花了些功夫修改正则表达式:

df3[df3['最高温'].isna()]

在这里插入图片描述
发现有两天数据只有一个值,我暂时把他丢弃。

df3=df3.dropna()
df3['温差']=df3['最高温'].astype('int')-df3['最低温'].astype('int')
df3

3.获取温差

在这里插入图片描述

df3.loc[df3['温差']<0]

在这里插入图片描述
有一天数据不符和左边下右边大的规则,可以修改下。

4.关系连接 merge

将处理好的df和含有温度信息的df3通过日期相连,这里两个日期的列名不同,需要手动指定。

注意保存df的index,如果不保存,连接后会形成新的index,原有的时间信息会丢失。

res1=df3[['日期','最高温','最低温','温差']]
df_index=df.index
df=df.merge(res1,left_on='date',right_on='日期',how='left').drop('date',1)
df.index=df_index
df

最终结果:
在这里插入图片描述

问题3:

当天是否有沙暴、是否有雾、是否有雨、是否有雪、是否为晴天

解决思路

1.contains

先看下有沙暴的

df3 = pd.read_csv('./data/qx1819.csv')
df3.loc[df3['天气'].str.contains('沙')]

在这里插入图片描述
设置新列记录雨雪雾

df3 = pd.read_csv('./data/qx1819.csv')
df3['沙暴']=df3['天气'].str.contains('沙').astype(int)
df3['有雾']=df3['天气'].str.contains('雾').astype(int)
df3['有雨']=df3['天气'].str.contains('雨').astype(int)
df3['有雪']=df3['天气'].str.contains('雪').astype(int)
df3

在这里插入图片描述

2.match+$

对于晴天不能用contains,因为这样会把阴转晴等也算在晴天
在这里插入图片描述
我妈可以使用match的方法,不过记得要匹配结尾,否则晴转多云等也会被匹配进去:

df3.loc[df3['天气'].str.match('晴$')]

在这里插入图片描述

注意这里endwith(‘晴’)也不行,会匹配多云转晴

在这里插入图片描述

df3['晴']=df3['天气'].str.match('晴$').astype(int)
df3

在这里插入图片描述

问题4:

选择一种合适的方法度量雨量/下雪量的大小(构造两个序列分别表示二者大小)

解决思路:

1.cat+contains获取所有含雨的天气类型

weather_type=df3['天气'].astype('category').cat.categories
rain_type=weather_type[rian_type.str.contains('雨')].tolist()
rain_type

一共42种,这里展示部分:
在这里插入图片描述

2.zip组成雨类型的字典

index1=[i for i in range(len(rain_type)) ]
rain_dict=dict(zip(rain_type, index1))
rain_dict

在这里插入图片描述

3.天气匹配下雨等级字典表

匹配不到的这里我用了异常捕获,填入变成缺失值

weather=df3['天气'].tolist()
rain=[]
for wea in weather:
    try:
        rain.append(rain_dict[wea])
    except:
        rain.append(np.NaN)
df3['下雨等级']=rain
df3

在这里插入图片描述
看下下雨等级非缺失值的那些:

df3.loc[df3['下雨等级'].notna()]

在这里插入图片描述

下雪等级情况完全一致,这里不再赘述

问题5:

限制只用4列,对风向进行0-1编码(只考虑风向,不考虑大小)

解决思路:

1.contains

这里题意也没完全弄懂,我按照自己的理解及出题人的回复就使用了最简单的做法,即当前风向中出现对应方向的风就将该列置为1,完成01编码,类似于one-hot向量,比如东北风转南风,出现了东、北、南,即东南西北四列分别为1101。
在这里插入图片描述

df3 = pd.read_csv('./data/qx1819.csv')
# pat_wind_dire='([东南西北]{1,2})风.([东南西北]{1,2})风|([东南西北]{1,2})风'
df3['东风']=df3['风向'].str.contains('东').astype(int)
df3['西风']=df3['风向'].str.contains('西').astype(int)
df3['南风']=df3['风向'].str.contains('南').astype(int)
df3['北风']=df3['风向'].str.contains('北').astype(int)
df3

在这里插入图片描述

其他思路:

群里小伙伴提供了另一种思路,不过由于时间原因无法继续实验:
在这里插入图片描述

就是先识别风向,然后对风向进行编码,最后对状态进行数据表示。 我的理解是,
识别风向:只有东西南北,以及东北、东南、西北、西南8种风向,先用extract提取 风向编码:可以用000-111编码
状态表示:感觉最后只需要两列,state1,state2,比如北风,应为000 NAN;东北风转北风 应为 101 000

剩余练习

对df的水压一列构造如下时序特征:

  • 当前时刻该站点水压与本月的相同整点时间该站点水压均值的差,例如当前时刻为2018-05-20 17:00:00,那么对应需要减去的值为当前月所有17:00:00时间点水压值的均值
    • 当前时刻所在周的周末该站点水压均值与工作日水压均值之差
    • 当前时刻向前7日内,该站点水压的均值、标准差、0.95分位数、下雨天数与下雪天数的总和
    • 当前时刻向前7日内,该站点同一整点时间水压的均值、标准差、0.95分位数
    • 当前时刻所在日的该站点水压最高值与最低值出现时刻的时间差
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值