优化python插值脚本时遇到问题
我正在为我掌握的一些公共交通数据插补到达时间。我有一个工作脚本,但它似乎运行在二次时间。以下是脚本:优化python插值脚本时遇到问题,python,csv,pandas,Python,Csv,Pandas,我正在为我掌握的一些公共交通数据插补到达时间。我有一个工作脚本,但它似乎运行在二次时间。以下是脚本: 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,Tru
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的链接:
我缩短了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\u datetime
将整个列转换为datetime64
s,而不是一次处理reindexed['arrival\u time']
中的每个值。一系列的datetime64
s具有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
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:只能使用带有datetimelike值的.dt访问器
:
事实上,正如您所指出的,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
使用正则表达式模式拆分到达时间字符串
r'(\d+)(\d+)(\d+)”
。它返回一个包含三列的数据帧
这段调试代码建议了一种解决方法。而不是pd.to\u 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])
因此,这似乎适用于现有的值,但似乎为所有空空格/空值分配了-61的值,并且不会在实际值之间插值。进一步检查后,每当调用pd.to_datetime()时,它都会用NAT替换所有NAN,这似乎会导致插值失败。然而,我仍然无法让插值工作。我已经发布了我得到的结果。这不是你看到的吗?所以我安装了sudopip——升级了pandas,看哪,插值就像你建议的那样工作。另外,感谢您提供的最佳实践。我很感激!我已经添加了一些关于如何调试错误、发生错误的原因以及解决方法的注释。
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