【问题标题】:Resample into equidistant time based on multiple indices基于多个索引重采样到等距时间
【发布时间】:2021-03-02 16:52:14
【问题描述】:

我有一个数据帧,其中包含一些与此类似的网络流

flow = {'date': ['2020-11-13 13:57:51','2020-11-13 13:57:51','2020-11-13 13:57:52','2020-11-13 13:59:53','2020-11-13 13:59:54'],
        'source_ip': ['192.168.1.1','192.168.1.2','10.0.0.1','192.168.1.1','192.168.1.1'],
        'destination_ip': ['10.0.0.1', '10.0.0.1', '192.168.1.1', '192.168.1.2', '192.168.1.2'],
        'source_bytes':[5,1,2,3,3]
        }

df = pd.DataFrame(flow, columns = ['date', 'source_ip', 'destination_ip', 'source_bytes']).set_index('date')

看起来像这样

date                | source_ip     | destination_ip| source_bytes
2020-11-13 13:57:51 | 192.168.1.1   | 10.0.0.1      | 5
2020-11-13 13:57:51 | 192.168.1.2   | 10.0.0.1      | 1 
2020-11-13 13:57:52 | 10.0.0.1      | 192.168.1.1   | 2
2020-11-13 13:59:53 | 192.168.1.1   | 192.168.1.2   | 3
2020-11-13 13:59:54 | 192.168.1.2   | 192.168.1.1   | 3

我想将它们重新采样为 1 分钟的刻度,但也按 ip 分组。然后source_bytes需要聚合,不管ip是在source_ip还是destination_ip中

应该变成这样。 (手动计算。希望这里没有做任何错误)。每分钟都应该表示所有 ip,但如果没有值则用零填充。

ip          | date                  | source_bytes_sum
192.168.1.1 | 2020-11-13 13:57:00   | 7
192.168.1.2 | 2020-11-13 13:57:00   | 1
10.0.0.1    | 2020-11-13 13:57:00   | 8
192.168.1.1 | 2020-11-13 13:59:00   | 6
192.168.1.2 | 2020-11-13 13:59:00   | 6
10.0.0.1    | 2020-11-13 13:59:00   | 0

这里相同的表示只是按 ip '分组'

ip          | date                  | source_bytes_sum
192.168.1.1 | 2020-11-13 13:57:00   | 7
            | 2020-11-13 13:59:00   | 6
192.168.1.2 | 2020-11-13 13:57:00   | 1
            | 2020-11-13 13:59:00   | 6
10.0.0.1    | 2020-11-13 13:57:00   | 8
            | 2020-11-13 13:59:00   | 0

我开始尝试以下方法,但仅按 source_ip 分组并忽略destination_ip。它也不会添加零值

grouped = df.groupby(['source_ip', pd.Grouper(key='date', freq='1min')])[['source_bytes']].agg(['sum'])
grouped

                                source_bytes
                                sum
source_ip   date    
10.0.0.1    2020-11-13 13:57:00 2
192.168.1.1 2020-11-13 13:57:00 5
            2020-11-13 13:59:00 6
192.168.1.2 2020-11-13 13:57:00 1

【问题讨论】:

  • 你研究过 pandas 的重采样功能吗? resample link
  • 是的,如我的示例所示。但不知道如何将source_ip和destination_ip组合到采样中。

标签: pandas time-series resampling


【解决方案1】:

首先通过DataFrame.melt 使用unpivot,然后使用Grouper0 值添加Series.unstackDataFrame.stack

df = (df.melt(['date', 'source_bytes'], value_name='ip')
        .groupby(['ip', pd.Grouper(key='date', freq='1min')])['source_bytes']
        .sum()
        .unstack(fill_value=0)
        .stack()
        .reset_index(name='sum'))
print (df)
            ip                date  sum
0     10.0.0.1 2020-11-13 13:57:00    8
1     10.0.0.1 2020-11-13 13:59:00    0
2  192.168.1.1 2020-11-13 13:57:00    7
3  192.168.1.1 2020-11-13 13:59:00    6
4  192.168.1.2 2020-11-13 13:57:00    1
5  192.168.1.2 2020-11-13 13:59:00    6

或使用DataFrame.stack 并附加source_bytesMultiIndexDataFrame.set_index

df = (df.set_index(['date','source_bytes'])
        .stack()
        .reset_index(name='ip')
        .groupby(['ip', pd.Grouper(key='date', freq='1min')])['source_bytes']
        .sum()
        .unstack(fill_value=0)
        .stack()
        .reset_index(name='sum')
       )
print (df)
            ip                date  sum
0     10.0.0.1 2020-11-13 13:57:00    8
1     10.0.0.1 2020-11-13 13:59:00    0
2  192.168.1.1 2020-11-13 13:57:00    7
3  192.168.1.1 2020-11-13 13:59:00    6
4  192.168.1.2 2020-11-13 13:57:00    1
5  192.168.1.2 2020-11-13 13:59:00    6

编辑:使用更多聚合函数:

df = pd.DataFrame(flow, columns = ['date', 'source_ip', 'destination_ip', 'source_bytes'])
df['date'] = pd.to_datetime(df['date'])


df2 = (df.melt(['date', 'source_bytes'], value_name='ip')
        .groupby(['ip', pd.Grouper(key='date', freq='1min')])['source_bytes']
        .agg(['sum','min','mean'])
        .unstack(fill_value=0)
        .stack()
        .reset_index()
        )
print (df2)
            ip                date  sum  min      mean
0     10.0.0.1 2020-11-13 13:57:00    8    1  2.666667
1     10.0.0.1 2020-11-13 13:59:00    0    0  0.000000
2  192.168.1.1 2020-11-13 13:57:00    7    2  3.500000
3  192.168.1.1 2020-11-13 13:59:00    6    3  3.000000
4  192.168.1.2 2020-11-13 13:57:00    1    1  1.000000
5  192.168.1.2 2020-11-13 13:59:00    6    3  3.000000

【讨论】:

  • 谢谢。我正在查看您的第一个解决方案,但得到以下输出 paste.ubuntu.com/p/sGs5FrpjB5
  • 是的,看起来好多了。只是另一个问题。如果我想将此扩展到更多字段,即destination_bytes, source_packets,以及更多聚合,即.agg(['sum','min','mean']),我需要为索引重置做什么?
  • 太棒了。通过添加额外的列也可以完美地工作
  • 嗨,我只是想知道如何确保 min(date) 和 max(date) 之间的所有分钟都显示为零值和每个 ip?
  • @Chris 仅在电话上,但不确定您的想法,也许是最好的发布新问题。
猜你喜欢
  • 2021-11-17
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2017-06-01
  • 2013-06-02
相关资源
最近更新 更多