我有一个如下的df
col1, mydate
1, 25-DEC-2016 09:15:00
2, 25-DEC-2016 10:14:00
3, 25-DEC-2016 10:16:00
4, 25-DEC-2016 10:18:56
2, 25-DEC-2016 11:14:00
2, 25-DEC-2016 10:16:00
df.info(): mydate 323809 non-null object
根据时间我需要这个数据帧,比如df的时间小于10:15:00,df的时间小于11:15:00
因此使用
创建了切片间隔times=[pd.to_datetime(i) for i in '10:15:00','11:15:00','12:15:00','13:15:00','14:15:00','15:15:00', '15:30:00']
然后我将我的mydate类型转换为时间 这花费了很多时间
df['mydate']=df4.mydate.apply(lambda x: pd.to_datetime(x,infer_datetime_format=True).time())
我认为上面的命令可以优化,或者应该有更好/更快的方式。
然后我就这么做了
for time in times:
slice = df[df.mydate<time.time()]
我的目的只是将df.mydate时间与['10:15:00','11:15:00','12:15:00','13:15:00','14:15:00','15:15:00', '15:30:00']
(但不是日期)进行比较,并简单地将子集df
以上方式适合我,但我正在寻找更好的方法。
其他: 有趣的是,使用
排序mydate非常快(即使我没有转换为mydate col到datetime)df.sort_values(by='mydate')
让我觉得我的子集化方式应该更快。
mydate col将始终采用25-DEC-2016 09:15:00
格式(注意DEC而非Dec)我可以使用format='%d-%b-%Y %H:%M:%S'
答案 0 :(得分:2)
首先,我建议在整个数组/系列上使用pd.to_datetime
,所以它会是:
pd.to_datetime(['10:15:00','11:15:00','12:15:00','13:15:00']).time
而不是
[pd.to_datetime(i).time() for i in ['10:15:00','11:15:00','12:15:00','13:15:00']]
其次,你对格式是正确的。正如pd.to_datetime
的文档所述,使用
pd.to_datetime(['25-DEC-2016 09:15:00', '25-DEC-2016 09:15:00'],
format='%d-%b-%Y %H:%M:%S')
而不是
pd.to_datetime(['25-DEC-2016 09:15:00', '26-DEC-2016 09:15:00'],
infer_datetime_format=True)
现在考虑您的数据框:
df = pd.DataFrame({'col1': [1, 2, 3, 2],
'mydate': ['25-DEC-2016 09:15:00',
'25-DEC-2016 11:15:00',
'26-DEC-2016 11:15:00',
'26-DEC-2016 12:15:00']})
>>>
col1 mydate
0 1 25-DEC-2016 09:15:00
1 2 25-DEC-2016 11:15:00
2 3 26-DEC-2016 11:15:00
3 2 26-DEC-2016 12:15:00
您可以先转换实际mydate
系列中的datetime
列:
df['mydate'] = pd.to_datetime(df.mydate, format='%d-%b-%Y %H:%M:%S')
然后,您就可以通过date
访问者访问time
和dt
字段(以及更多内容):
df.mydate.dt.date
>>>
0 2016-12-25
1 2016-12-25
2 2016-12-26
3 2016-12-26
df.mydate.dt.time
>>>
0 09:15:00
1 11:15:00
2 11:15:00
3 12:15:00
因此,在计算切片时,您可以使用:
for time in times:
slice = df[df.mydate.dt.time < time]
print(time, slice, sep='\n')
>>>
10:15:00
col1 mydate
0 1 2016-12-25 09:15:00
11:15:00
col1 mydate
0 1 2016-12-25 09:15:00
12:15:00
col1 mydate
0 1 2016-12-25 09:15:00
1 2 2016-12-25 11:15:00
2 3 2016-12-26 11:15:00
13:15:00
col1 mydate
0 1 2016-12-25 09:15:00
1 2 2016-12-25 11:15:00
2 3 2016-12-26 11:15:00
3 2 2016-12-26 12:15:00
注意你得到的实际上不是切片,因为它们有重叠的记录,所以你可能想要使用类似的东西:
for start, end in zip(times, times[1:]):
slice = df[(start <= df.mydate.dt.time) & (df.mydate.dt.time <= end)]
作为最后一点,您可以使用pandas中的group by操作获取使用for循环尝试完成的任务。您只需准备一个mytime
列,仅包含时间:
df['mytime'] = df.mydate.dt.time
groups = df.groupby('mytime')
for group_key, group_df in groups:
print(group_key, group_df, sep='\n')
>>>
09:15:00
col1 mydate mytime
0 1 2016-12-25 09:15:00 09:15:00
11:15:00
col1 mydate mytime
1 2 2016-12-25 11:15:00 11:15:00
2 3 2016-12-26 11:15:00 11:15:00
12:15:00
col1 mydate mytime
3 2 2016-12-26 12:15:00 12:15:00
不错的是,您不需要对单个数据帧进行操作,但您可以同时对每个组应用相同的操作和聚合:
groups.size()
>>>
mytime
09:15:00 1
11:15:00 2
12:15:00 1
groups.sum()
>>>
col1
mytime
09:15:00 1
11:15:00 5
12:15:00 2
答案 1 :(得分:1)
我相信<html>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid
#d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.translate(10,10);
ctx.fillRect(70,40,44,30);
ctx.fillRect(10,10,40,30);
</script>
</body>
</html>
更适合在熊猫中工作 - 所以首先split
字符串列和选择转换时间:
timedelta
转换df['mydate'] = pd.to_timedelta(df['mydate'].str.split().str[1])
print (df)
col1 mydate
0 1 09:15:00
1 2 10:14:00
2 3 10:16:00
3 4 10:18:56
4 2 11:14:00
5 2 10:16:00
:
list
最后创建切片:
times=pd.to_timedelta(['10:15:00','11:15:00','12:15:00',
'13:15:00','14:15:00','15:15:00', '15:30:00'])
print (times)
TimedeltaIndex(['10:15:00', '11:15:00', '12:15:00', '13:15:00', '14:15:00',
'15:15:00', '15:30:00'],
dtype='timedelta64[ns]', freq=None)