【问题标题】:Fast Approach to add rows for all dates between two columns in Dataframe在 Dataframe 中的两列之间为所有日期添加行的快速方法
【发布时间】:2020-04-27 04:06:15
【问题描述】:

我需要一种快速的方法来为两列之间的所有日期添加行。我已经尝试了以下方法:

df.index.repete: add rows for all dates between two columns?

pd.melt: How can I add rows for all dates between two columns?

date_range + 合并: Get all dates between startdate and enddate columns

迭代器: Add rows to dataframe each day between a range of two columns

使用 sqlite 的 SQL 脚本:尝试在两个日期之间进行连接时导致机器崩溃。

当他们工作时,它们都非常慢(在 25 到 75 分钟之间),我的数据框中有 120 万行,扩展到超过 3000 万行。无论如何,是否可以使用应用或矢量化之类的方法来执行这些解决方案?有没有办法在最多几分钟内做到这一点?

数据具有以下结构:

start_date   end_date     ID

最终的结构应该是:

start_date   end_date     Date     ID

【问题讨论】:

  • 您介意发布df["start_date"].min()df["end_date"].max() 我需要创建一个可重现的示例
  • 您能否分享足够的代码/数据让我们能够测试任何潜在的解决方案?

标签: python pandas


【解决方案1】:

日历计算 (pd.date_range) 比生成整数序列 (np.arange) 慢很多。您列出的答案非常简单优雅,但速度不是很快。您的数据量需要不同的解决方案。

此答案假定 ID 对于每一行都是唯一的。在我的 iMac 2015 上,100 万行大约需要 4.5 秒。最终的数据帧有大约 2500 万行。

import itertools

# `date_range` is slow so we only call it once
all_dates = pd.date_range(df['start_date'].min(), df['end_date'].max())

# For each day in the range, number them as 0, 1, 2, 3, ...
rank = all_dates.to_series().rank().astype(np.int64) - 1

# Change from `2020-01-01` to "day 500 in the all_dates array", for example
start = df['start_date'].map(rank).values
end = df['end_date'].map(rank).values

# This is where the magic happens. For each row, instead of saying
# `start_date = Jan 1, 2020` and `end_date = Jan 10, 2020`, we are
# creating a range of days: [500, 501, ... 509]
indices = list(itertools.chain.from_iterable([range(s,e+1) for s,e in zip(start, end)]))

# Now map day 500 back to Jan 1, 2020, day 501 back to Jan 2, 2020, and so on
dates = np.take(all_dates, indices)

# Align the rest of the columns to the expanded dates
duration = (end - start + 1).astype(np.int64)
ids = np.repeat(df['ID'], duration)
start_date = np.repeat(df['start_date'], duration)
end_date = np.repeat(df['end_date'], duration)

# Assemble the result
result = pd.DataFrame({
    'start_date': start_date,
    'end_date': end_date,
    'ID': ids,
    'Date': dates
})

【讨论】:

  • 这不起作用,说“ValueError:数组长度 300527269 与索引长度 301745242 不匹配”。我检查了,ID 并不像我想象的那样是唯一的。
  • 我可能在优化过程中引入了一个错误。尝试将range(s,e) 更改为range(s,e+1)
猜你喜欢
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
相关资源
最近更新 更多