【问题标题】:split a column into N groups by value differences (timestamp)按值差异(时间戳)将一列分成 N 组
【发布时间】:2019-12-22 10:03:07
【问题描述】:

.csv 格式的样本数据

| No.|   IP     |      Unix_time     |    # integer unix time
| 1  | 1.1.1.1  |     1563552000     |    # equivalent to 12:00:00 AM
| 2  | 1.1.1.1  |     1563552030     |    # equivalent to 12:00:30 AM
| 3  | 1.1.1.1  |     1563552100     |    # equivalent to 12:01:40 AM
| 4  | 1.1.1.1  |     1563552110     |    # equivalent to 12:01:50 AM
| 5  | 1.1.1.1  |     1563552180     |    # equivalent to 12:03:00 AM
| 6  | 1.2.3.10 |     1563552120     |    

这是使用 pandas groupby( )get_group( ) 函数的当前工作代码:

data = pd.read_csv(some_path, header=0)
root = data.groupby('IP')

for a in root.groups.keys():
    t = root.get_group(a)['Unix_time']
    print(a + 'has' + t.count() + 'record')

您将看到以下结果:

1.1.1.1 has 5 record
1.2.3.10 has 1 record

现在,我想根据上面的代码进行一些改进。

对于相同的 IP 值(例如,1.1.1.1),我想根据最大时间间隔(例如,60 秒)制作更多 子组 ,并计算每个子组中的元素数量。例如,在上面的示例数据中:

从第 1 行开始:第 2 行 Unix_time 值在 60​​ 秒内,但第 3 行超过 60 秒。

因此,第 1-2 行是一个组,第 3-4 行是一个单独的组,第 5 行是一个单独的组。换句话说,组 '1.1.1.1' 现在有 3 个子组。结果应该是:

1.1.1.1 start time 1563552000 has 2 record within 60 secs
1.1.1.1 start time 1563552100 has 2 record within 60 secs
1.1.1.1 start time 1563552150 has 1 record within 60 secs
1.2.3.10 start time 1563552120 has 1 record within 60 secs

如何制作?

【问题讨论】:

  • 在我看来,第 5 行应该根据您描述的规则与第 3 行和第 4 行分组,因为第 3、4 和 5 行都发生在从 1563552100 开始的 100 秒窗口内。什么我误会了吗?
  • @moormanly:是的,我犯了一个错误。我修改。

标签: python pandas pandas-groupby


【解决方案1】:

你可以使用pd.Grouper:

df['datetime'] = pd.to_datetime(df['Unix_time'], unit='s')
for n, g in df.groupby(['IP', pd.Grouper(freq='60s', key='datetime')]):
    print(f'{n[0]} start time {g.iloc[0, g.columns.get_loc("Unix_time")]} has {len(g)} records within 60 secs')

输出:

1.1.1.1  start time 1563552000 has 2 records within 60 secs
1.1.1.1  start time 1563552100 has 2 records within 60 secs
1.1.1.1  start time 1563552150 has 1 records within 60 secs
1.2.3.10 start time 1563552120 has 1 records within 60 secs

使用“根”和整数:

root = df.groupby(['IP',df['Unix_time']//60])

for n, g in root:
     print(f'{n[0]} start time {g.iloc[0, g.columns.get_loc("Unix_time")]} has {len(g)} records within 60 secs')

输出:

1.1.1.1  start time 1563552000 has 2 records within 60 secs
1.1.1.1  start time 1563552100 has 2 records within 60 secs
1.1.1.1  start time 1563552150 has 1 records within 60 secs
1.2.3.10 start time 1563552120 has 1 records within 60 secs

【讨论】:

  • 在我的例子中,df 是 root.get_group(a)?
  • 可以不使用to_datetime吗?如果我只想将它们读为整数
  • 它仅适用于我的示例数据。但是如果时间是例如 1563557387 和 1563557418。它们在 60 秒之内,但是它们的 //60 值(26059289 和 26059290)是不同的,所以不要属于同一组
  • 是的,最好转换为日期时间
  • 我测试了datetime方法,它总是从分钟的00秒开始计算,而不是每组的真正开始时间。
猜你喜欢
  • 2020-08-28
  • 2023-02-08
  • 2019-07-21
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2011-10-13
  • 2015-06-27
  • 1970-01-01
相关资源
最近更新 更多