首页 > 解决方案 > pandas 合并彼此相距不到 20 秒的交互

问题描述

如果它们彼此相距 0-20 秒,我正在尝试合并我的交互数据集。

我的 CSV 文件的第一行:

Source,     Target,     time_start, time_end,  total_time
0x597E5627, 0x3C992634, 1532,       1583,      51
0x597E5627, 0x3C992634, 1627,       1652,      25
0x597E5627, 0x3C992634, 1755,       2492,      737
0x597E5627, 0x3C3A21AD, 2649,       2681,      32
0x597E5627, 0x3C3A21AD, 3028,       3058,      30
0x597E5627, 0x3C3A21AD, 3071,       3094,      23

输出应该是什么(注意最后一行):

Source,     Target,     time_start,  time_end,  total_time
0x597E5627, 0x3C992634, 1532,        1583,    51
0x597E5627, 0x3C992634, 1627,        1652,    25
0x597E5627, 0x3C992634, 1755,        2492,    737
0x597E5627, 0x3C3A21AD, 2649,        2681,    32
0x597E5627, 0x3C3A21AD, 3028,        3094,    53

因为最后一次交互是 time_start 3071- time_end 3058 = 13 秒,所以我认为这仍然是 1 次对话。

现在代码似乎工作。我成功地找到了需要合并的案例,并制作了一个累积列表,列出了我的数据中发生了哪些交互组,但我的输出只显示了秒数,并过滤掉了我的芯片名称。

import pandas as pd
df = pd.read_csv('filter20seconds.csv')

start_end_differences = df.time_start  - df.time_end.shift(1)
threshold_selector = start_end_differences > 20 
groups = threshold_selector.cumsum()
new = df.groupby(groups).agg({'time_start':min, 'time_end':max, 
      'total_time':sum})

print(new)

有没有人发现我做错了什么,源和目标的名称消失了?

我现在的输出:

     time_start  time_end  total_time
0          1532      1583          51
1          1627      1652          25
2          1755      2492         737
3          2649      2681          32
4          3028      3094          53

------------- 出现问题 ----

Source,     Target,     time_start, time_end, total_time
0x6979EF0C, 0x300C163D, 6049,       6083,     34
0x6979EF0C, 0x300C163D, 6125,       6236,     111
0x15697F98, 0x3C3A21AD, 1855,       1875,     20
0x15697F98, 0x064F5882, 2749,       2776,     27
0x15697F98, 0x064F5882, 3040,       3078,     38

在这里,计算为 1855-6236 的行将被合并,因为它低于 20。

标签: pythonpandasmerge

解决方案


假设您构建一个以索引为节点的图

import networkx as nx
import itertools

G = nx.Graph()
G.add_nodes_from(df.index)

将距离小于 20 的所有行对添加屁股边缘:

G.add_edges_from(
    [(r1[0], r2[0]) for (r1, r2) in itertools.product(df.iterrows(), df.iterrows()) if r1[0] < r2[0] and r1[1]['time_end'] + 20 > r2[1]['time_start']]
)

现在找到所有连接组件:

groups = dict(itertools.chain.from_iterable([[(ee, i) for ee in e] for (i, e) in enumerate(nx.connected_components(G))]))
>>> df.index.map(lambda j: groups[j])
Int64Index([0, 1, 2, 3, 4, 4], dtype='int64')

请注意,4 和 5 已被正确识别为属于同一组。

此时,您只需要以groups通常的方式进行分组。例如,对于开始时间:

>>> df.time_start.groupby(df.index.map(lambda j: groups[j])).min()
0    1532
1    1627
2    1755
3    2649
4    3028
Name: time_start, dtype: int64

推荐阅读