【问题标题】:Transform rows with start_date and end_date to daily rows将带有 start_date 和 end_date 的行转换为每日行
【发布时间】:2021-05-19 04:44:24
【问题描述】:

我有一个数据框 df,每个 id 有一个条目或每个 id 有重叠条目:

start_date | end_date   | id | col1 | col2 | ...
2020-10-01 | 2020-10-01 | a  | 2    | 3    | ...
2020-10-01 | 2020-10-03 | a  | 4    | 5    | ...
2020-10-02 | 2020-10-07 | b  | 7    | 8    | ...
2020-10-06 | 2020-10-08 | b  | 9    | 10   | ...
2020-10-06 | 2020-10-08 | c  | k    | p    | ...

我需要为每一行创建从 start_date 到 end_date 的天数。

最终结果应如下所示:

date       | id | col1 | col2 | ...
2020-10-01 | a  | 2    | 3    | ...
2020-10-01 | a  | 4    | 5    | ...
2020-10-02 | a  | 4    | 5    | ...
2020-10-03 | a  | 4    | 5    | ...
2020-10-02 | b  | 7    | 8    | ...
2020-10-03 | b  | 7    | 8    | ...
2020-10-04 | b  | 7    | 8    | ...
2020-10-05 | b  | 7    | 8    | ...
2020-10-06 | b  | 7    | 8    | ...
2020-10-07 | b  | 7    | 8    | ...
2020-10-06 | b  | 9    | 10   | ...
2020-10-07 | b  | 9    | 10   | ...
2020-10-08 | b  | 9    | 10   | ...
2020-10-06 | c  | k    | p    | ...
2020-10-07 | c  | k    | p    | ...
2020-10-08 | c  | k    | p    | ...

我有大约 1000 万行,这种转换需要每天进行多次,所以转换必须很快。我发现的所有解决方案都使用 apply/lambdas,并且在我的 PC 上需要大约 20-30 分钟,这太慢了。

我试过melt+groupby:https://stackoverflow.com/a/57334167/4435175 但是生成的数据框缺少 start_date 和 end_date 之间的日期。

有什么快速的方法吗?

【问题讨论】:

  • melt 可以做到吗?
  • I have ~10 million rows and this transformation needs to be done multiple times a day, - 不确定是否存在针对此问题的快速 pandas 解决方案
  • @sammywemmy - 哟,melt + groupby 重新索引
  • @sammywemmy - 我喜欢itertuples 喜欢here,但我觉得还是很慢:(

标签: pandas date


【解决方案1】:

一个想法是使用DataFrame.itertuples,但如果数据非常大,它应该很慢:

s = pd.concat([pd.Series(r.Index,pd.date_range(r.start_date, r.end_date)) 
                     for r in df.itertuples()])
# print (s)

df = df.drop(['start_date','end_date'], 1).join(pd.DataFrame({'Date':s.index}, index=s))
print (df)
  id col1 col2       Date
0  a    2    3 2020-10-01
1  a    4    5 2020-10-01
1  a    4    5 2020-10-02
1  a    4    5 2020-10-03
2  b    7    8 2020-10-02
2  b    7    8 2020-10-03
2  b    7    8 2020-10-04
2  b    7    8 2020-10-05
2  b    7    8 2020-10-06
2  b    7    8 2020-10-07
3  b    9   10 2020-10-06
3  b    9   10 2020-10-07
3  b    9   10 2020-10-08
4  c    k    p 2020-10-06
4  c    k    p 2020-10-07
4  c    k    p 2020-10-08

【讨论】:

  • 谢谢,我的数据集大约需要 300 秒,这比我的旧解决方案快得多,但遗憾的是仍然太慢了。
  • @Vega - 我知道,很遗憾。
  • @Vega - 不可能使用 sql 解决方案,例如将值转换为 mysql 并加入那里?
  • 我可以将它放入 sqlite.db,在那里查询,然后将其作为 pd.DataFrame 取回,但我不知道如何在 SQL 中从 start_date/end_date 创建日期。
  • 我将使用您的代码对我的数据进行预处理,然后使用保存的 parquet 文件,现在可以使用。非常感谢。
猜你喜欢
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 2019-05-17
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
相关资源
最近更新 更多