我正在为我拥有的一些公共交通数据插入到达时间。我有一个工作脚本,但它似乎在二次时间内运行。这是脚本:
import pandas as pd
#read the txt file
st = pd.read_csv('interpolated_test.csv')
# sort first by trip_id, then by stop_sequence
sorted_st = st.sort(['trip_id','stop_sequence'], ascending=[False,True])
# reset the index values in prep. for iteration
reindexed = sorted_st.reset_index(drop=True)
# for each row in 'arrival_time' that has a value of hh:mm:ss
for i in reindexed['arrival_time']:
# for i in range(len(reindexed['arrival_time'])):
if pd.isnull(i) == False:
# splice hh:mm:ss
hour = int(i[:2])
minute = int(i[3:5])
# assign hh:mm:ss to numeric value
minute_value = (hour * 60) + minute
# replace current string with int value
# takes ~655s to execute on Macbook Pro w/ entire stop_times.txt
# runs in quadratic time
reindexed = reindexed.replace(i,minute_value)
# interpolate and write out
new = reindexed.apply(pd.Series.interpolate)
print(new)
这是csv的链接:https://gist.github.com/adampitchie/0192933ed0eba122ba7e
我缩短了 csv,以便您可以运行文件而无需等待它完成。
对于任何熟悉熊猫的人来说,这应该是唾手可得的果实,但我被困住了,任何帮助将不胜感激。
[更新]所以我尝试使用完整的 CSV 文件运行相同的代码,但出现此错误:
Traceback (most recent call last):
File "/Users/tester/Desktop/ETL/interpolate.py", line 49, in <module>
reindexed[col].dt.hour * 60
File "pandas/src/properties.pyx", line 34, in pandas.lib.cache_readonly.__get__ (pandas/lib.c:40664)
File "/Library/Python/2.7/site-packages/pandas/core/series.py", line 2513, in dt
raise TypeError("Can only use .dt accessor with datetimelike values")
TypeError: Can only use .dt accessor with datetimelike values
看起来pd.to_datetime(reindexed[col])
不起作用。这是代码,为了完成:
import pandas as pd
st = pd.read_csv('csv/stop_times.csv')
sorted_st = st.sort(['trip_id','stop_sequence'], ascending=[False,True])
reindexed = sorted_st.reset_index(drop=True)
for col in ('arrival_time', 'departure_time'):
reindexed[col] = pd.to_datetime(reindexed[col])
reindexed[col] = (
reindexed[col].dt.hour * 60
+ reindexed[col].dt.minute)
reindexed[col] = reindexed[col].interpolate()
print(reindexed.iloc[:, :3])
只要有可能,请尝试将计算表述为对整列而不是行的操作,或者逐项操作。您可以使用 pd.to_datetime
将整个列转换为 datetime64
,而不是一次处理一个reindexed['arrival_time']
中的每个值。一系列datetime64
具有dt
属性,允许您以整数形式访问小时和分钟。因此,您可以像这样表示整个列的计算:
for col in ('arrival_time', 'departure_time'):
reindexed[col] = pd.to_datetime(reindexed[col])
reindexed[col] = (
reindexed[col].dt.hour * 60
+ reindexed[col].dt.minute)
reindexed[col] = reindexed[col].interpolate()
print(reindexed.iloc[:5, :3])
收益 率
trip_id arrival_time departure_time
0 1423492 647.000000 647.000000
1 1423492 649.666667 649.666667
2 1423492 652.333333 652.333333
3 1423492 655.000000 655.000000
4 1423492 655.750000 655.750000
调试TypeError: Can only use .dt accessor with datetimelike values
:
事实上,正如你所指出的,pd.to_datetime
并没有将时间转换为 datetime64s。相反,它是只是返回与字符串相同的数据。 pd.to_datetime
在尝试将输入转换为日期时间时遇到错误时返回输入。您可以通过添加 errors='raise'
参数来收集有关出错的更多信息:
pd.to_datetime(reindexed['arrival_time'], errors='raise')
提高
ValueError: hour must be in 0..23
所以啊哈 - 时间格式可能有小时数超过23的时间。
用
col = 'arrival_time'
x = reindexed[col]
mask = x.str.extract(r'(d+):(d+):(d+)')[0].astype('int') > 23
我们可以看到小时数大于 23 的行示例:
In [48]: x[mask].head()
Out[48]:
42605 26:09:00
42610 26:12:00
42611 26:20:00
42612 26:30:00
42613 26:35:00
Name: arrival_time, dtype: object
x.str.extract 使用正则表达式模式拆分到达时间字符串 r'(d+):(d+):(d+)'
.它返回一个包含三列的数据帧。
这段调试代码建议了一种解决方法。而不是pd.to_datetime
,我们可以用x.str.extract
来查找小时和分钟:
import pandas as pd
st = pd.read_csv('csv/stop_times.csv')
sorted_st = st.sort(['trip_id','stop_sequence'], ascending=[False,True])
reindexed = sorted_st.reset_index(drop=True)
for col in ('arrival_time', 'departure_time'):
df = reindexed[col].str.extract(
r'(?P<hour>d+):(?P<minute>d+):(?P<second>d+)').astype('float')
reindexed[col] = df['hour'] * 60 + df['minute']
reindexed[col] = reindexed[col].interpolate()
print(reindexed.iloc[:5, :3])
收益 率
trip_id arrival_time departure_time
0 1423492 647.000000 647.000000
1 1423492 649.666667 649.666667
2 1423492 652.333333 652.333333
3 1423492 655.000000 655.000000
4 1423492 655.750000 655.750000