【问题标题】:Speeding up iterator operation in python加快python中的迭代器操作
【发布时间】:2019-05-19 21:14:08
【问题描述】:
[pd.Series(pd.date_range(row[1].START_DATE, row[1].END_DATE)) for row in df[['START_DATE', 'END_DATE']].iterrows()]

有没有办法加快这个操作? 基本上对于给定的日期范围,我在它们之间创建所有日期行。

【问题讨论】:

  • 创建一个系列列表没有意义...介意解释一下您正在尝试做什么,这样您就可以获得比表面答案更好的答案,这些答案可能会或可能不会解决您的问题?跨度>
  • 好的,好好谈谈!
  • 没有必要讽刺。让您知道手头的问题是创建一个 df,在其中我可以拥有与两个日期之间的所有日期相对应的行,然后将其绘制在 ID 与日期交叉表上。

标签: python pandas numpy


【解决方案1】:

使用DataFrame.itertuples:

L = [pd.Series(pd.date_range(r.START_DATE, r.END_DATE)) for r in df.itertuples()]

或两列的 zip:

L = [pd.Series(pd.date_range(s, e)) for s, e in zip(df['START_DATE'], df['END_DATE'])]

如果想加入:

s = pd.concat(L, ignore_index=True)

100 行的性能:

np.random.seed(123)

def random_dates(start, end, n=100):

    start_u = start.value//10**9
    end_u = end.value//10**9

    return pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s')

start = pd.to_datetime('2015-01-01')
end = pd.to_datetime('2018-01-01')
df = pd.DataFrame({'START_DATE': start, 'END_DATE':random_dates(start, end)})
print (df)

In [155]: %timeit [pd.Series(pd.date_range(row[1].START_DATE, row[1].END_DATE)) for row in df[['START_DATE', 'END_DATE']].iterrows()]
33.5 ms ± 145 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [156]: %timeit [pd.date_range(row[1].START_DATE, row[1].END_DATE) for row in df[['START_DATE', 'END_DATE']].iterrows()]
30.3 ms ± 1.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [157]: %timeit [pd.Series(pd.date_range(r.START_DATE, r.END_DATE)) for r in df.itertuples()]
25.3 ms ± 218 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [158]: %timeit [pd.Series(pd.date_range(s, e)) for s, e in zip(df['START_DATE'], df['END_DATE'])]
24.3 ms ± 594 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

对于 1000 行:

start = pd.to_datetime('2015-01-01')
end = pd.to_datetime('2018-01-01')
df = pd.DataFrame({'START_DATE': start, 'END_DATE':random_dates(start, end, n=1000)})

In [159]: %timeit [pd.Series(pd.date_range(row[1].START_DATE, row[1].END_DATE)) for row in df[['START_DATE', 'END_DATE']].iterrows()]
333 ms ± 3.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [160]: %timeit [pd.date_range(row[1].START_DATE, row[1].END_DATE) for row in df[['START_DATE', 'END_DATE']].iterrows()]
314 ms ± 36.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [161]: %timeit [pd.Series(pd.date_range(s, e)) for s, e in zip(df['START_DATE'], df['END_DATE'])]
243 ms ± 1.49 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [162]: %timeit [pd.Series(pd.date_range(r.START_DATE, r.END_DATE)) for r in df.itertuples()]
246 ms ± 2.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

  • itertuples 更快吗?
  • @Mysterious - 当然,更快。
  • 那个加入正是我以后要做的事情!
  • Zip 版本更快!完美。
  • @Mysterious - 是的,真实数据的最佳测试,也取决于 DataFrame 的大小。
【解决方案2】:

不要在每次迭代时创建pd.Series,而是:

[pd.date_range(row[1].START_DATE, row[1].END_DATE))
 for row in df[['START_DATE', 'END_DATE']].iterrows()]

并根据结果创建一个数据框。这是一个例子:

df = pd.DataFrame([
     {'start_date': pd.datetime(2019,1,1), 'end_date': pd.datetime(2019,1,10)},
     {'start_date': pd.datetime(2019,1,2), 'end_date': pd.datetime(2019,1,8)}, 
     {'start_date': pd.datetime(2019,1,6), 'end_date': pd.datetime(2019,1,14)} 
])

dr = [pd.date_range(df.loc[i,'start_date'], df.loc[i,'end_date']) for i,_ in df.iterrows()]

pd.DataFrame(dr)

      0          1          2          3          4          5  \
0 2019-01-01 2019-01-02 2019-01-03 2019-01-04 2019-01-05 2019-01-06   
1 2019-01-02 2019-01-03 2019-01-04 2019-01-05 2019-01-06 2019-01-07   
2 2019-01-06 2019-01-07 2019-01-08 2019-01-09 2019-01-10 2019-01-11   

       6          7          8          9  
0 2019-01-07 2019-01-08 2019-01-09 2019-01-10  
1 2019-01-08        NaT        NaT        NaT  
2 2019-01-12 2019-01-13 2019-01-14        NaT  

【讨论】:

  • 我很难相信有人会使用这种格式的数据。我希望 OP 在 cmets 中回答我的澄清,否则我会将其作为一个失败的原因写下来......
  • 是的,在这种情况下,IMO 建议其他方法比加快当前解决方案的方法更有意义。因为确实系列列表没有意义
猜你喜欢
  • 2011-10-22
  • 1970-01-01
  • 2015-05-26
  • 2015-05-20
  • 1970-01-01
  • 2020-07-15
  • 2014-12-29
  • 2011-02-23
相关资源
最近更新 更多