Day12-Python综合练习2(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 2(Inference) 4(float) precision type 1(resnet50)
1(resnet50)  model average 2(inference) time :  3(13.426570892333984) ms

问题:整理为如下样式

请把日志结果进行整理,变换成如下状态model_i用相应模型名称填充,按照字母顺序排序,数值保留三位小数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UX850xtL-1610545546369)(attachment:image.png)]

思路

1.观察给定的数据,首先需要做的是将数据导入进来

2.将1,2,3,4的数据提取出来

3.将2和4组合为列,1为行,3作为值

import pandas as pd 
import numpy as np
import re

【START】

1. 读取数据

使用re模块读取两个值之间的数据,此处可以直接将开始和结尾的多余数据直接删除,然后读取txt文件,但是考虑到日常的使用,选择使用这种方式

file = open('benchmark.txt')
keyStart = 'memory_available: 129118310400'
keyEnd = 'benchmark end :  2020/12/24 12:56:47'
buff = file.read()
pat = re.compile(keyStart+'(.*?)'+keyEnd, re.S)
result = pat.findall(buff) #得到我们实际想要的数据
file.close()

2.调整数据格式

上面获取的数据读取出来是一个列表,存成了一列,观察数据发现可以通过/n拆分,但是拆分出来的列表的并没有按照一条完整的日志数据来存储,接着将列表数据拆分为奇数列和偶数列,得到我们想要的一条完整的日志记录存在在一行

A = result
#将数据依据\n拆分
A = A[0].split('\n')
#去除多余数据
A = A[1:len(A)-1]
# 获取奇数列和偶数列
J = [i for i in A if A.index(i)%2 == 0]
Q = [i for i in A if A.index(i)%2 == 1]
#将奇数列和偶数列拼成DataFrame
df = pd.DataFrame({
     'A':J,
                  'B': Q})
df.head(2)
A B
0 Benchmarking Training float precision type mna... mnasnet0_5 model average train time : 28.527...
1 Benchmarking Training float precision type mna... mnasnet0_75 model average train time : 34.10...

3.提取值

A列:提取2,4 ;B列提取1,3

#通过正则提取到2和4
s1 = df['A']
p = 'Benchmarking( \w+)( \w+)'
ext1 = s1.str.extract(p)
s2 = df['B']
#提取到1,2,3。注意获取浮点型数据的方法
p2 = '(\w+)  model average (\w+) time :  (\d+.\d+)'
ext2 = s2.str.extract(p2)
#拼接1,2,3,4
data = pd.DataFrame({
     'name': ext2[0],
                    'type': ext1[0]+'_'+ext1[1],
                    'time': round(ext2[2].astype('float'),3)})#截取为小数点后三位,注意需要转换为float型
data.head(3)
name type time
0 mnasnet0_5 Training_ float 28.528
1 mnasnet0_75 Training_ float 34.105
2 mnasnet1_0 Training_ float 34.314

4. 长表变宽表

data = data.pivot(index='name',columns='type',values='time')
data = data.reset_index()
data.head()
type name Inference_ double Inference_ float Inference_ half Training_ double Training_ float Training_ half
0 densenet121 144.111 15.637 19.772 417.207 93.357 88.976
1 densenet161 511.177 31.750 27.555 1290.287 136.624 144.319
2 densenet169 175.808 21.598 26.371 511.404 104.840 121.556
3 densenet201 223.960 26.169 33.394 654.365 129.334 118.940
4 mnasnet0_5 11.870 8.039 6.929 48.232 28.528 27.198

【END】

总结

这道题的总体思路是比较好找到的,但是遇到了几个问题:

1.首先就是读取数据,需要排除我们不要的数据,这里是在网上查找了一个获取开始和结束值之间数据的方法

2.数据获取了之后发现存的是一个长字符串,观察之后选择将数据拆分,需要注意的是要先转换为字符串之后再拆分,拆分完以后,发现我们需要的数据存成了两行,这里又将两行转换为两列

上面两个问题解决后终于将我们的数据整理成了可以进行各种操作的数据集,之后就是通过正则表达式将我们需要的数据提取,然后再进行长宽表变换,最后就得到了我们的最终数据

二、水压站点的特征工程

df1和df2中分别给出了18年和19年各个站点的数据,其中列中的H0至H23分别代表当天0点至23点;df3中记录了18-19年的每日该地区的天气情况,请完成如下的任务:

df1 = pd.read_csv('yali18.csv')
df2 = pd.read_csv('yali19.csv')
df3 = pd.read_csv('qx1819.csv')
df1.tail(2)
Time MeasName H0 H1 H2 H3 H4 H5 H6 H7 ... H14 H15 H16 H17 H18 H19 H20 H21 H22 H23
10948 2018-12-31 站点9 0.287250 0.301875 0.30600 0.30525 0.313500 0.301500 0.279750 0.253875 ... 0.241500 0.237750 0.233625 0.227625 0.209625 0.226500 0.21975 0.211500 0.241125 0.246375
10949 2018-12-31 站点6 0.313125 0.330375 0.33375 0.33450 0.337125 0.326625 0.310875 0.277875 ... 0.261375 0.259125 0.262125 0.252750 0.241500 0.252375 0.24675 0.239625 0.269250 0.269625

2 rows × 26 columns

df2.head(2)
Time MeasName H0 H1 H2 H3 H4 H5 H6 H7 ... H14 H15 H16 H17 H18 H19 H20 H21 H22 H23
0 2019-01-01 站点4 0.342000 0.429375 0.4290 0.44025 0.445875 0.444750 0.417750 0.387000 ... 0.319875 0.32625 0.323625 0.322500 0.309000 0.307125 0.307125 0.307125 0.307125 0.307125
1 2019-01-01 站点7 0.215125 0.239500 0.2575 0.24625 0.275125 0.264625 0.229375 0.205375 ... 0.180625 0.17650 0.181375 0.155125 0.159625 0.146125 0.144625 0.135250 0.158875 0.184750

2 rows × 26 columns

1. 通过df1和df2构造df,把时间设为索引,第一列为站点编号,第二列为对应时刻的压力大小

思路

使用纵向拼接将df1和df2数据集合并,然后需要将H0-H23转换为对应的时间点,之后通过宽表变长表将日期和时间匹配

【START】

1. 拼接数据

df = pd.concat([df1,df2],axis=0,join='outer')
df.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
1 2018-01-01 站点7 0.214375 0.226750 0.232375 0.233125 0.235 0.23275 0.230875 0.220000 ... 0.187375 0.19675 0.19975 0.19225 0.186250 0.18325 0.17725 0.163375 0.165250 0.199375

2 rows × 26 columns

2. 将H0-H23替换为时间值

#1.使用正则将H去除
timet = pd.Series(df.columns[2:])
p = 'H(\d+)'
timet = timet.str.extract(p)[0].to_list()
#2.在前面填充0,否则在后面拼接的时候0:00:00不显示
timet = [' '+i.zfill(2)+':00:00' for i in timet]
#3.替换原来的列名,这里将列名补全,可以直接替换
timet1 = ['Date','站点']+timet
df.columns = timet1
df.head(2)
Date 站点 00:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 ... 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00
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
1 2018-01-01 站点7 0.214375 0.226750 0.232375 0.233125 0.235 0.23275 0.230875 0.220000 ... 0.187375 0.19675 0.19975 0.19225 0.186250 0.18325 0.17725 0.163375 0.165250 0.199375

2 rows × 26 columns

3.将宽表变为长表

#转换为长表,然后将日期和时间拼接为一个字段
df_melted = df.melt(id_vars=['Date','站点'],
                   value_vars=timet,
                   var_name='Time2',
                   value_name='压力')
df_melted['Time'] = pd.to_datetime(df_melted['Date']+df_melted['Time2'])
df_new = df_melted[['Time','站点','压力']]
#将Time作为索引
df_new = df_new.set_index('Time')
df_new.tail(3)
站点 压力
Time
2019-12-31 23:00:00 站点2 0.332000
2019-12-31 23:00:00 站点9 0.201375
2019-12-31 23:00:00 站点6 0.000000

【END】

2. 在上一问构造的df基础上,构造下面的特征序列或DataFrame,并把它们逐个拼接到df的右侧

2.1 当天最高温、最低温和它们的温差

df3.head(3)
日期 天气 气温 风向
0 2018-01-01 多云 1C~-4C 东南风 微风
1 2018-01-02 阴转多云 8C~0C 东北风 3-4级
2 2018-01-03 阴转小雪 1C~-1C 东北风 4-5级转4-5级

【START】

思路

首先我们需要将df3的气温拆成最低气温和最高气温,并存成数值型,计算出温差使用join拼入df中

#删除气温为空的值
df_t = df3.dropna(how='any',subset=['气温'])
s = df_t['气温']
#将空格和℃替换为统一值,方便正则取值
s = s.str.replace(' ','')
s = s.str.replace('℃','C')
#正则表达式取出温度
p = '(\d+)C~(\S\d+|\d+)'
ext = s.str.extract(p)
#由于存在没有最低温度的值,这里选择不为na的值
ext = ext[ext[0].isna()==False]
#将类型转换为int型,方便计算差值
ext[0] = ext[0].astype(int)
ext[1] = ext[1].astype(int)
ext[2] = ext[0] - ext[1] 
ext.head(2)
0 1 2
0 1 -4 5
1 8 0 8

上面一步出现了问题:首先是会有存在空格的现象,采用替代的Day3-Index.ipynb将空格删除出;另一个会有没有最低温度的值,因为只有两条,这里选择将其删除

#使用索引拼接的方式,上面删除na值不会影响到索引号
df_t = df_t.join(ext,how='outer')
#对列名重命名
df_t = df_t.rename(columns = {
     0:'最高气温',1:'最低气温',2:'温差'})
df_t = df_t[['日期','最高气温','最低气温','温差']]
df_t['日期'] = pd.to_datetime(df_t['日期'])
df_te = df_new.copy()
#对第1小问生成的df_new进行改造,建立拼接字段date
df_m = df_te.reset_index(drop=False)
#注意使用merge的时候,两个日期的类型要一致
df_m['date'] = pd.to_datetime(df_m['Time'].dt.date)
df_l = df_m.merge(df_t, left_on = 'date', right_on='日期', how='left')
df_l.head(2)
Time 站点 压力 date 日期 最高气温 最低气温 温差
0 2018-01-01 站点4 0.402750 2018-01-01 2018-01-01 1.0 -4.0 5.0
1 2018-01-01 站点7 0.214375 2018-01-01 2018-01-01 1.0 -4.0 5.0

【END】

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

思路

我们想要返回布尔类型,因此可以直接使用str.contains,然后再拼接数据

【START】

df_w = df3.copy()
#日期类型转换
df_w['日期'] = pd.to_datetime(df_w['日期'])
s = df_w['天气']
s1 = s.str.contains('沙|暴')
#此处注意一定要重新命名,默认名称为天气,在join的时候会报错
s1 = s1.rename('是否沙暴')
s2 = s.str.contains('雾')
s2 = s2.rename('是否有雾')
s3 = s.str.contains('雨')
s3 = s3.rename('是否有雨')
s4 = s.str.contains('雪')
s4 = s4.rename('是否有雪')
s5 = s.str.contains('晴')
s5 = s5.rename('是否晴天')
#将上面的结果拼接到df_w中
df_w = df_w.join(s1,how='left')
df_w = df_w.join(s2,how='left')
df_w = df_w.join(s3,how='left')
df_w = df_w.join(s4,how='left')
df_w = df_w.join(s5,how='left')
df_w.tail(2)
日期 天气 气温 风向 是否沙暴 是否有雾 是否有雨 是否有雪 是否晴天
727 2019-12-30 阴转晴 4℃~-6℃ 东北风转北风 4-5级转4-5级 False False False False True
728 2019-12-31 晴转多云 0℃~-5℃ 西风转南风 <3级 False False False False True
#将df_w数据拼接到df_l
df_l = df_l.merge(df_w, left_on = 'date', right_on='日期', how='left')
df_e = df_l[['Time','站点','压力','date','天气','气温','风向','最高气温','最低气温','温差','是否沙暴','是否有雾','是否有雨','是否有雪','是否晴天']]
df_e.tail(2)
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 是否沙暴 是否有雾 是否有雨 是否有雪 是否晴天
525598 2019-12-31 23:00:00 站点9 0.201375 2019-12-31 晴转多云 0℃~-5℃ 西风转南风 <3级 0.0 -5.0 5.0 False False False False True
525599 2019-12-31 23:00:00 站点6 0.000000 2019-12-31 晴转多云 0℃~-5℃ 西风转南风 <3级 0.0 -5.0 5.0 False False False False True

【END】

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

思路

雨量使用水压站点当天的最大压力来度量,下雪量的大小通过天气中的雪的类型来区分,设置为分类数据类型

【START】

雨量的分类

#筛选出有雨的数据
df_y = df_e[df_e['是否有雨']==True]
gb = df_y.groupby('date')['压力'].max()
#依据gb的最大值和最小值来进行分组,分为小、中、大、特大四类
print(gb.min())
print(gb.max())
0.40424999594688416
1.4006251096725464
#对雨量进行分类
s = pd.cut(gb, bins=4, labels=['小','中','大','特大'])

雪量的分类

#筛选出有雪的数据
df_x = df_e[df_e['是否有雪']==True]
pat = '(\w雪)'
typ = df_x['天气'].str.extract(pat)
typ[0].unique()
#我们发现提取后,雪的分类可以设置为四类,现在需要将四类作为有序分类
array(['小雪', '中雪', '夹雪', '大雪'], dtype=object)
#设置为有序分类
typ = typ[0].astype('category')
typ = typ.cat.reorder_categories(['夹雪','小雪', '中雪', '大雪'],ordered=True)

将雨和雪的分类拼接

#修改为DataFrame,s使用值连接
s = pd.DataFrame(s)
s = s.reset_index()
df_f = df_e.merge(s,on ='date',how='left')
#typ使用索引连接
typ = pd.DataFrame(typ)
df_f = df_f.join(typ,how='outer')
df_f = df_f.rename(columns={
     '压力_x':'压力','压力_y':'雨量大小',0:'雪量大小'})
df_f[df_f['是否有雨']==True].head(2)
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 是否沙暴 是否有雾 是否有雨 是否有雪 是否晴天 雨量大小 雪量大小
450 2018-01-16 站点4 0.396375 2018-01-16 雨夹雪转阴 4C~-1C 东北风转南风 3-4级转3-4级 4.0 -1.0 5.0 False False True True False 夹雪
451 2018-01-16 站点7 0.209500 2018-01-16 雨夹雪转阴 4C~-1C 东北风转南风 3-4级转3-4级 4.0 -1.0 5.0 False False True True False 夹雪

【END】

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

思路

首先查看一下风向的种类,发现有很多类别,这里选取后两位作为它的主要风向(这里我认为并不是最优的)

【START】

#获取风向的数据,并以后两位作为主要风向
p ='(转\w+风|\w+风)'
df_d  = df_f['风向'].str.extract(p)
df_d = pd.DataFrame([str(i)[-2:] for i in df_d[0].to_list()])
#转换为4列0-1编码
df_d = pd.get_dummies(df_d[0])
df_d = df_d[['东风','西风','南风','北风']]
#将风向数据拼入df_f,索引连接
df_h = df_f.join(df_d,how='outer')
df_h.tail(2)
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 ... 是否有雾 是否有雨 是否有雪 是否晴天 雨量大小 雪量大小 东风 西风 南风 北风
525598 2019-12-31 23:00:00 站点9 0.201375 2019-12-31 晴转多云 0℃~-5℃ 西风转南风 <3级 0.0 -5.0 5.0 ... False False False True NaN NaN 0 0 1 0
525599 2019-12-31 23:00:00 站点6 0.000000 2019-12-31 晴转多云 0℃~-5℃ 西风转南风 <3级 0.0 -5.0 5.0 ... False False False True NaN NaN 0 0 1 0

2 rows × 21 columns

【END】

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

3.1 当前时刻该站点水压与本月的相同整点时间该站点水压均值的差,例如当前时刻为2018-05-20 17:00:00,那么对应需要减去的值为当前月所有17:00:00时间点水压值的均值

思路

首先计算按月到时刻、站点的均值,然后拼接到主表,最后进行计算

【START】

#对df进行改造,新增月和时刻的列值
df = pd.DataFrame(df_h[['Time','date','站点','压力','是否有雨','是否有雪']])
df['month'] = df['Time'].dt.month
df['hour'] = df['Time'].dt.hour
df.head()
Time date 站点 压力 是否有雨 是否有雪 month hour
0 2018-01-01 2018-01-01 站点4 0.402750 False False 1 0
1 2018-01-01 2018-01-01 站点7 0.214375 False False 1 0
2 2018-01-01 2018-01-01 站点22 0.247000 False False 1 0
3 2018-01-01 2018-01-01 站点21 0.284250 False False 1 0
4 2018-01-01 2018-01-01 站点20 0.292875 False False 1 0
#到月到时段的均值计算
df_month = df.groupby(['month','hour','站点'])['压力'].mean()
df_month = df_month.reset_index()
df_month.head()
month hour 站点 压力
0 1 0 站点1 0.260095
1 1 0 站点10 0.259512
2 1 0 站点11 0.244476
3 1 0 站点12 0.252960
4 1 0 站点13 0.259923
#将到月的数据拼接到df,使用值拼接
df = df.merge(df_month, on=['month','hour','站点'],how='left')
df = df.sort_values(by=['站点','hour'],axis=0,ascending=True)
df = df.rename(columns={
     '压力_x':'压力','压力_y':'平均压力'})
df[(df['站点']=='站点1')&df['hour']==1].head(3)
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力
21909 2018-01-01 01:00:00 2018-01-01 站点1 0.292000 False False 1 1 0.266966
21939 2018-01-02 01:00:00 2018-01-02 站点1 0.291625 False False 1 1 0.266966
21969 2018-01-03 01:00:00 2018-01-03 站点1 0.296500 False True 1 1 0.266966

【END】

3.2 当前时刻所在周的周末该站点水压均值与工作日水压均值之差

思路

首先找到站点的周末和工作日,然受计算周末和工作日的均值,最后再按照站点、年、月、周进行汇总

【START】

#增加年、周、工作日维度
df['year'] = df['Time'].dt.year
df['week'] = df['Time'].dt.isocalendar().week
df['day_week'] = df['Time'].dt.dayofweek
df.head(2)
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力 year week day_week
9 2018-01-01 2018-01-01 站点1 0.288625 False False 1 0 0.260095 2018 1 0
39 2018-01-02 2018-01-02 站点1 0.286750 False False 1 0 0.260095 2018 1 1
#周末的水压均值
df_m = df[df['day_week'].isin([5,6])]
df_m2 = df_m.groupby(['站点','year','month','week'])['压力'].mean()
df_m2 = df_m2.reset_index()
df_m2 = df_m2.rename(columns={
     '压力':'周末平均压力'})
df_m2.head(2)
站点 year month week 周末平均压力
0 站点1 2018 1 1 0.251711
1 站点1 2018 1 2 0.248945
#工作日的水压均值
df_w = df[df['day_week'].isin([0,1,2,3,4])]
df_w2 = df_w.groupby(['站点','year','month','week'])['压力'].mean()
df_w2 = df_w2.reset_index()
df_w2 = df_w2.rename(columns={
     '压力':'工作日平均压力'})
df_w2.head(2)
站点 year month week 工作日平均压力
0 站点1 2018 1 1 0.253222
1 站点1 2018 1 2 0.252750
#拼接数据
df = df.merge(df_m2, on=['站点','year','month','week'],how='left')
df = df.merge(df_w2, on=['站点','year','month','week'],how='left')
#做差值
df['周末与工作日压力差值'] = df['周末平均压力'] - df['工作日平均压力']
df.tail(2)
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力 year week day_week 周末平均压力 工作日平均压力 周末与工作日压力差值
525598 2019-12-30 23:00:00 2019-12-30 站点9 0.225375 False False 12 23 0.247349 2019 1 0 NaN 0.218828 NaN
525599 2019-12-31 23:00:00 2019-12-31 站点9 0.201375 False False 12 23 0.247349 2019 1 1 NaN 0.218828 NaN

【END】

3.3 当前时刻向前7日内,该站点水压的均值、标准差、0.95分位数、下雨天数与下雪天数的总和

思路

我理解这一问求得是到日的结果,不到时刻对应的结果,按照每个不同的站点,使用rolling移动求出相对应的值,这里仅实现了均值,其他的可以参照这个方法实现,但是使用rolling会将当天也算在7天内,这是一个bug点

【START】

s = df.copy()
#得到到单日的均值
f = pd.DataFrame(s.groupby(['date','站点'])['压力'].mean())
f = f.reset_index()
#创建站点的序列,以便下面的循环
z = pd.Series(s['站点'].unique())
for i in z:
#给定到站点
    s = f[f['站点']==i]
#要使用rolling,所以字段仅为日期和压力
    s = s[['date','压力']]
#对date进行一个排序
    s = s.sort_values(by='date')
#设置索引
    s1 = s.set_index('date')
#rolling取7天均值
    r = s1.rolling(window=7)
    r1 = r.mean()
#将站点的值拼入r1中
    m = pd.DataFrame([i]*r1.shape[0],index=s['date'].to_list(),columns=['站点'])
    n = pd.concat([r1,m],1)
#得到最终结果
    result = pd.concat([result,n])
result[result['站点']=='站点2']
压力 站点
2018-01-01 NaN 站点2
2018-01-02 NaN 站点2
2018-01-03 NaN 站点2
2018-01-04 NaN 站点2
2018-01-05 NaN 站点2
... ... ...
2019-12-27 0.335159 站点2
2019-12-28 0.335098 站点2
2019-12-29 0.334743 站点2
2019-12-30 0.335152 站点2
2019-12-31 0.335009 站点2

2920 rows × 2 columns

【END】

3.4 当前时刻向前7日内,该站点同一整点时间水压的均值、标准差、0.95分位数

思路

依照上面的方法,我们多加一个时刻的参数即可

【START】

s = df.copy()
#得到到单日的均值
f = s[['Time','hour','站点','压力']]
#创建站点的序列,以便下面的循环
z = pd.Series(s['站点'].unique())
t = pd.Series(s['hour'].unique())
for i in z:
    for j in t:
#给定到站点
        s = f[f['站点']==i]
#要使用rolling,所以字段仅为日期和压力
        s = s[s['hour']==j]
        s = s[['Time','压力']]
#对date进行一个排序
        s = s.sort_values(by='Time')
#设置索引
        s1 = s.set_index('Time')
#rolling取7天均值
        r = s1.rolling(window=7)
        r1 = r.mean()
#将站点的值拼入r1中
        m = pd.DataFrame([i]*r1.shape[0],index=s['Time'].to_list(),columns=['站点'])
        n = pd.concat([r1,m],1)
#得到最终结果
        result = pd.concat([result,n])
result[result['站点']=='站点2']
压力 站点
2018-01-01 00:00:00 NaN 站点2
2018-01-02 00:00:00 NaN 站点2
2018-01-03 00:00:00 NaN 站点2
2018-01-04 00:00:00 NaN 站点2
2018-01-05 00:00:00 NaN 站点2
... ... ...
2019-12-27 23:00:00 0.338964 站点2
2019-12-28 23:00:00 0.339286 站点2
2019-12-29 23:00:00 0.339982 站点2
2019-12-30 23:00:00 0.341054 站点2
2019-12-31 23:00:00 0.339714 站点2

20440 rows × 2 columns

3.5 当前时刻所在日的该站点水压最高值与最低值出现时刻的时间差

思路

先求出当前日的水压最高点和最低点时刻,然后再算时间差

【START】

#找到水压的最高点,先通过groupby找到最高点的值,然后再通过merge的inner找到最高点的时段
df5 = df_e.copy()
df1 = df5.groupby(['站点','date'])['压力'].max()
#这里出现了一个问题,最大值和最小值存在多条记录的情况,所以选择在对Time取最大值
df_n = df5.merge(df1,on=['站点','date','压力'],how='inner')
df_n = pd.DataFrame(df_n.groupby(['站点','date'])['Time'].max())
df_max = df_n.reset_index()
df_max = df_max.rename(columns={
     'Time':'max_time'})
#找到水压的最高点,先通过groupby找到最高点的值,然后再通过merge的inner找到最高点的时段
df2 = df5.groupby(['站点','date'])['压力'].min()
df_n = df5.merge(df2,on=['站点','date','压力'],how='inner')
#这里最小值存在多值的问题选择最小值
df_n = pd.DataFrame(df_n.groupby(['站点','date'])['Time'].min())
df_min = df_n.reset_index()
df_min = df_min.rename(columns={
     'Time':'min_time'})
#通过date和站点将最大值和最小值拼接
df_f = df_max.merge(df_min, on=['date','站点'],how='outer')
df_f['time_diff'] = df_f['max_time'] -df_f['min_time'] 
df_f.sort_values(by=['date'])
df_f = df_f[['date','站点','time_diff']]
df_f.head(2)
date 站点 time_diff
0 2018-01-01 站点1 -1 days +18:00:00
1 2018-01-02 站点1 -1 days +18:00:00

【END】

总结

在题目2中遇到的最大的问题是,当写了很多条赋值语句的时候,命名如果不具有代表性,很难清晰的知道之前的含义,在之后的学习中一定要规避这个问题,尽量将名称认真的取名。

整个做题的过程中,大部分的思维方式都是基于表格运算的思维方式,这个方式可以解决问题,但是可能并不是最优的方案,之后还需要更多的去了解python内的知识,转变自己的思维方式。

最后,要养成写备注的习惯!!!

你可能感兴趣的