【问题标题】:Aggregate efficiently between dates在日期之间有效聚合
【发布时间】:2022-01-13 20:49:49
【问题描述】:

你好,我有一个像这样的 Df:

  HostName      Date        
0   B   2021-01-01 12:42:00
1   B   2021-02-01 12:30:00  
2   B   2021-02-01 12:40:00  
3   B   2021-02-25 12:40:00  
4   B   2021-03-01 12:41:00  
5   B   2021-03-01 12:42:00  
6   B   2021-03-02 12:43:00  
7   B   2021-03-03 12:44:00  
8   B   2021-04-04 12:44:00  
9   B   2021-06-05 12:44:00  
10  B   2021-08-06 12:44:00  
11  B   2021-09-07 12:44:00  
12  A   2021-03-12 12:45:00  
13  A   2021-03-13 12:46:00  

我如何聚合这是我解决问题的方法,但它根本没有效率,如果有 1M 行 需要很长时间 有没有更好的方法来有效地在日期之间进行聚合?

最终结果:

  HostName      Date        ds
0   B   2021-01-01 12:42:00  1
1   B   2021-02-01 12:30:00  2
2   B   2021-02-01 12:40:00  3
3   B   2021-02-25 12:40:00  3
4   B   2021-03-01 12:41:00  2
5   B   2021-03-01 12:42:00  3
6   B   2021-03-02 12:43:00  4
7   B   2021-03-03 12:44:00  5
8   B   2021-04-04 12:44:00  1
9   B   2021-06-05 12:44:00  1
10  B   2021-08-06 12:44:00  1
11  B   2021-09-07 12:44:00  1
12  A   2021-03-12 12:45:00  1
13  A   2021-03-13 12:46:00  2
TheList = []
for index, row in df.iterrows():
    TheList.append((df[(df['Date'] > (df['Date'].iloc[index] - pd.DateOffset(months=1))) & (df['Date'] <= df['Date'].iloc[index])].groupby(['HostName']).size()[row[0]]))
df['ds'] = TheList

有没有更好的方法来做到这一点,但结果相同?

【问题讨论】:

  • 你能解释一下你想如何聚合吗?
  • 就像下面的代码一样,它只是根据每行的两个日期进行效率聚合,根据主机名创建聚合
  • @sammywemmy 我相信这个数据框预期的输出。看起来 OP 正在尝试生成 ds 列。

标签: python pandas performance


【解决方案1】:

这里用于组之间的广播,Trues 在GroupBy.transform 的自定义函数中使用sum

注意:性能还取决于组的长度,如果这里的几个非常大的组应该是内存问题。

df['Date'] = pd.to_datetime(df['Date'])

def f(x):
    a = x.to_numpy()
    b = x.sub(pd.DateOffset(months=1)).to_numpy()
    return np.sum((a > b[:, None]) & (a <= a[:, None]), axis=1)

df['ds'] = df.groupby('HostName')['Date'].transform(f)

print (df)
   HostName                Date  ds
0         B 2021-01-01 12:42:00   1
1         B 2021-02-01 12:30:00   2
2         B 2021-02-01 12:40:00   3
3         B 2021-02-25 12:40:00   3
4         B 2021-03-01 12:41:00   2
5         B 2021-03-01 12:42:00   3
6         B 2021-03-02 12:43:00   4
7         B 2021-03-03 12:44:00   5
8         B 2021-04-04 12:44:00   1
9         B 2021-06-05 12:44:00   1
10        B 2021-08-06 12:44:00   1
11        B 2021-09-07 12:44:00   1
12        A 2021-03-12 12:45:00   1
13        A 2021-03-13 12:46:00   2

如果内存问题,很遗憾需要循环:

df['Date'] = pd.to_datetime(df['Date'])
df['Date1'] = pd.to_datetime(df['Date']).sub(pd.DateOffset(months=1))

def f(x):
    one = x['Date'].to_numpy()
    both = x[['Date','Date1']].to_numpy()
    
    x['ds'] = [np.sum((one > b) & (one <= a))  for a, b in both]
    return x

df = df.groupby('HostName').apply(f)
print (df)
   HostName                Date               Date1  ds
0         B 2021-01-01 12:42:00 2020-12-01 12:42:00   1
1         B 2021-02-01 12:30:00 2021-01-01 12:30:00   2
2         B 2021-02-01 12:40:00 2021-01-01 12:40:00   3
3         B 2021-02-25 12:40:00 2021-01-25 12:40:00   3
4         B 2021-03-01 12:41:00 2021-02-01 12:41:00   2
5         B 2021-03-01 12:42:00 2021-02-01 12:42:00   3
6         B 2021-03-02 12:43:00 2021-02-02 12:43:00   4
7         B 2021-03-03 12:44:00 2021-02-03 12:44:00   5
8         B 2021-04-04 12:44:00 2021-03-04 12:44:00   1
9         B 2021-06-05 12:44:00 2021-05-05 12:44:00   1
10        B 2021-08-06 12:44:00 2021-07-06 12:44:00   1
11        B 2021-09-07 12:44:00 2021-08-07 12:44:00   1
12        A 2021-03-12 12:45:00 2021-02-12 12:45:00   1
13        A 2021-03-13 12:46:00 2021-02-13 12:46:00   2

【讨论】:

  • 谢谢。但是我无法分配具有数组形状的 637gb (827195,827195)
  • @MAS - 所以这意味着有像Notice 中提到的大团体?
  • 是的,有 2700 万行可能有不同的方法来获得相同的结果
  • @MAS - 添加了新的解决方案,它应该比有问题的解决方案更快。
猜你喜欢
  • 2014-12-18
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 2021-07-28
  • 2018-06-11
相关资源
最近更新 更多