优化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