pandas技巧太多了,往往有想法但无从下手,话不多说,开始
图一转换为图二:实现不同时间段都按10分钟的精度去划分,并且实现一行变多行
![](https://i-blog.csdnimg.cn/blog_migrate/101426f431c21ebe8a93d903da12ee9b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78809a5f90561bc72e2b78d4791c9a75.png)
该函数是用来将不是10分钟整的时间设置为10分钟整的类型:采用四舍五入取舍数据。
import datetime
#时间划分函数(StartTime:开始时间,EndTime:结束时间)
def TimeClassfy(StartTime,EndTime):
Start1 = int((StartTime.split(':')[1])[0:1]) #开始十位
End1 = int((EndTime.split(':')[1])[0:1]) #结束十位
Start2 = int((StartTime.split(':')[1])[1:2]) #开始个位
End2 = int((EndTime.split(':')[1])[1:2]) #结束个位
#字符串转时间类型
StartTime = datetime.datetime.strptime(StartTime,"%H:%M:%S")
EndTime = datetime.datetime.strptime(EndTime,"%H:%M:%S")
#计算时间间隔(跨0点)
dar = EndTime - (StartTime - datetime.timedelta(days=1)) if EndTime < StartTime else EndTime - StartTime
#将时间类型转化为字符串类型
def Utiler(StartTime,EndTime):
StartTime = StartTime.strftime('%H:%M:%S')
EndTime = EndTime.strftime('%H:%M:%S')
return StartTime,EndTime
#结束时间分钟为整数
if End2 == 0:
if dar < datetime.timedelta(minutes=10):
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
else:
if Start2 >= 5:
StartTime = StartTime+datetime.timedelta(minutes=+10-Start2)
else:
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
return Utiler(StartTime,EndTime)
elif Start1 == End1:
if dar < datetime.timedelta(minutes=10):
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
EndTime = EndTime+datetime.timedelta(minutes=+10-End2)
else:
if Start2 >= 5:
StartTime = StartTime+datetime.timedelta(minutes=+10-Start2)
else:
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
if End2 >= 5:
EndTime = EndTime+datetime.timedelta(minutes=+10-End2)
else:
EndTime = EndTime+datetime.timedelta(minutes=-End2)
return Utiler(StartTime,EndTime)
elif (End2-0) >= (10-Start2):
if End2 >= 5 and Start2 < 5:
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
EndTime = EndTime+datetime.timedelta(minutes=+10-End2)
return Utiler(StartTime,EndTime)
else:
StartTime = StartTime+datetime.timedelta(minutes=+10-Start2)
EndTime = EndTime+datetime.timedelta(minutes=+10-End2)
return Utiler(StartTime,EndTime)
elif (End2-0) < (10-Start2):
if End2 >= 5:
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
EndTime = EndTime+datetime.timedelta(minutes=+10-End2)
return Utiler(StartTime,EndTime)
else:
StartTime = StartTime+datetime.timedelta(minutes=-Start2)
EndTime = EndTime+datetime.timedelta(minutes=-End2)
return Utiler(StartTime,EndTime)
错误做法:使用apply方法根据原表多列属性生成一个表------错误地方:apply是根据一行或一列操作,每一行生成一个表会出现:could not broadcast input array from shape (x,y) into shape (x) ,这里我的做法是生成一个list
import numpy as np
import pandas as pd
import matplotlib
#时间分割函数(按10分钟的精度划分)
def TimeSlice(TUCASEID,start,end,TRCODE,state):
#将输入的字符串转化为时间类型,由于判断两个时间间隔是否10分钟内
less_start = datetime.datetime.strptime(start,'%H:%M:%S')
less_end = datetime.datetime.strptime(end,'%H:%M:%S')
#时间间隔不足10分时,less为True
if less_end < less_start:
less_start = less_start - datetime.timedelta(days=1)
less = True if (less_end-less_start) < datetime.timedelta(minutes=10) else False
#10分钟划分函数
startby = TimeClassfy(start,end)[0]
endby = TimeClassfy(start,end)[1]
#处理成时间类型,便于计算
datestart = datetime.datetime.strptime(startby,'%H:%M:%S')
dateend = datetime.datetime.strptime(endby,'%H:%M:%S')
FourTime = datetime.datetime.strptime('04:00:00','%H:%M:%S')
dateend = dateend - datetime.timedelta(minutes=10)
#处理不足10分钟的活动
if dateend <= datestart:
dateend+=datetime.timedelta(minutes=10)
data_list = list()
timestand = datetime.datetime.strptime('00:00:00','%H:%M:%S')
#1.开始时间少于或等于结束时间的情况
if datestart <= dateend:
#1.1 开始时间少于或等于结束时间,时间间隔少于10分钟
if less:
data_list.append(datestart.strftime('%H:%M:%S'))
#1.2 开始时间少于或等于结束时间,时间间隔大于10分钟
else:
#1.2.1 开始时间少于4点(解决最后一个时间段的问题),则令EndTime='04:00:00'
if datestart < FourTime and dateend > FourTime:
dateend = FourTime
while datestart <= dateend:
data_list.append(datestart.strftime('%H:%M:%S'))
datestart+=datetime.timedelta(minutes=10)
#2.开始时间在24点前,结束时间24点后的情况
else:
#2.1如果结束时间在4点后
if dateend > FourTime:
dateend = FourTime
#2.2开始时间在24点前,结束时间24点后
while datestart <= (timestand-datetime.timedelta(minutes=10) + datetime.timedelta(days=1)):
data_list.append(datestart.strftime('%H:%M:%S'))
datestart+=datetime.timedelta(minutes=10)
while timestand < dateend:
data_list.append(timestand.strftime('%H:%M:%S'))
timestand+=datetime.timedelta(minutes=10)
return ','.join(data_list)
关键在于将每行生成的list保持在新的列中,col.str.split(',',expand=True)一列分多列,在重塑(Stack),重塑后要重设第二级索引,series转dataframe,列换名,去除多余列并拼接。
#在原表里添加一列临时开始时间列表
finadf['STARTTEMP'] = finadf.apply(lambda row:TimeSlice(row['TUCASEID'], row['TUSTARTTIM'], row['TUSTOPTIME'],row['TRCODE'],row['state']), axis=1)
#将临时开始时间列表分成多列
t1 = finadf['STARTTEMP'].str.split(',', expand=True)
#关键:使用此方法可以实现根据列属性,将表一行变多行
t2 = t1.stack()
t3 = t2.reset_index(level=1, drop=True)
t4 = t3.to_frame()
t4.rename(columns={0:'TUSTARTTIM'},inplace=True)
#去除多余列并拼接新的列
DataTable = finadf.drop(['TUSTARTTIM','TUSTOPTIME','STARTTEMP'], axis=1).join(t4)
DataTable.head(50)