问题描述
timestamp
0 09/May/2016:10:53:30
1 09/May/2016:10:54:30
2 09/May/2016:10:55:30
3 09/May/2016:10:56:30
4 09/May/2016:10:57:30
5 09/May/2016:10:58:30
6 09/May/2016:10:59:30
格式为day/month/year:hours:minutes:seconds
我需要为每个时间戳计算两分钟的时间段。但这里的问题是日期格式错误,无法与 pandas to_period
函数一起使用。我试过了:
df['Period'] = pd.to_datetime(df['timestamp']).dt.to_period(minute=2,errors='coerce')
但这会引发异常:
UnkNown string format
预期输出如下:
timestamp Period
0 09/May/2016:10:53:30 1
1 09/May/2016:10:54:30 1
2 09/May/2016:10:55:30 1
3 09/May/2016:10:56:30 2
4 09/May/2016:10:57:30 2
5 09/May/2016:10:58:30 2
6 09/May/2016:10:59:30 3
任何建议将不胜感激。
解决方法
错误来自您拥有的日期格式。您可能需要将您的月份名称转换为数字,例如可以 --> "05" 指定格式:
date_format = "%d/%m/%Y:%H:%M:%S"
dict_months = {
"January": "01","February": "02","March": "03","April": "04","May": "05","June": "06","July": "07","August": "08","September": "09","October": "10","November": "11","December": "12"
}
这将使错误消失......
它有点脏,(可能存在原生的 Pandas 函数来做它,¯_(ツ)_/¯),但这里有一个解决方案:
# define your start date and a period,and then after every period minutes increment the value of period like this
start_date = pd.to_datetime("09/05/2016:10:53:30",format=date_format)
period = 2
time_period_func = lambda x: int(1 + ((x - start_date).total_seconds()//60 ) // (period+1))
df["period"] = pd.to_datetime(df["timestamp"].replace(dict_months,regex=True),format=date_format).apply(time_period_func)
基本上,您可以获得当前日期和开始之间的时间增量(以分钟为单位)。然后你应用一个简单的公式,通过除以 timedelta bu period 得到周期。
编辑 1: 我的回答没有考虑秒,只考虑时间戳的分钟部分! 如果您也想考虑秒数,请查看@ThePyGuy 的答案,我认为这是正确的方法
,您需要可以将正确的 formatting
传递给 pd.to_datetime
>>timestamp = pd.to_datetime(df['timestamp'],format='%d/%b/%Y:%H:%M:%S')
>>timestamp
0 2016-05-09 10:53:30
1 2016-05-09 10:54:30
2 2016-05-09 10:55:30
3 2016-05-09 10:56:30
4 2016-05-09 10:57:30
5 2016-05-09 10:58:30
6 2016-05-09 10:59:30
Name: timestamp,dtype: datetime64[ns]
现在,您可以计算从第一行开始经过的时间,得到以秒为单位的时间差,然后除以 120 (=2 Minutes)
,最后取整。
你最终会得到类似
>>periods=((timestamp - timestamp.iloc[0]).dt.total_seconds()/120).round()
>>periods
0 0.0
1 1.0
2 1.0
3 2.0
4 2.0
5 2.0
6 3.0
Name: timestamp,dtype: float64
您可能已经注意到第一个值是 0.0,这很明显,因为我们正在减去第一行的相同值,您可以将此值替换为 1。
periods.iloc[0] = 1
所以最终输出变成:
>>periods
0 1.0
1 1.0
2 1.0
3 2.0
4 2.0
5 2.0
6 3.0
Name: timestamp,dtype: float64
您也可以针对其他一些数据验证此方法..
>>timestamp
0 2016-05-09 10:53:30
1 2016-05-09 10:58:30
2 2016-05-09 10:59:30
3 2016-05-09 11:20:30
4 2016-05-09 11:25:30
5 2016-05-09 11:30:30
6 2016-05-09 11:31:30
periods=((timestamp - timestamp.iloc[0]).dt.total_seconds()/120).round()
periods.iloc[0] = 1
输出:
>>periods
0 1.0
1 2.0
2 3.0
3 14.0
4 16.0
5 18.0
6 19.0
Name: timestamp,dtype: float64