【问题标题】:Concatenating data frame rows based on column condition根据列条件连接数据框行
【发布时间】:2020-05-10 16:12:25
【问题描述】:

后面的讨论,我会参考下面的示例数据框:

现在,我希望实现的是对所有相似的数据包时间进行分组 - 即所有 7 秒、12 秒等。此外,PacketTime 字段应包含最小值和最大值的差异 (max(PacketTime) - min(PacketTime)) ,而FrameLenIPLenTCPLen 字段应该是对应于分组时间的所有值的列表。例如对于 7s 组,FrameLen 将包含c(304, 276, 276)

我的解决方法如下:

df <- packets %>%
  group_by(round(PacketTime)) %>%
  summarise(
    PTime=max(PacketTime)-min(PacketTime),
    FLen=list(FrameLen),
    ILen=list(IPLen),
    Movement=0
  ) %>%
  rename(PacketTime=PTime) %>%
  rename(FrameLen=FLen) %>%
  rename(IPLen=ILen)
df$"round(PacketTime)" <- NULL # Remove the group_by

但是,其中一些交叉(即 1480 还包括 1481 的一部分)。这里的部分使这更容易(在某些方面)是每个组都由 5s 时间窗口分隔(通过 Python time.sleep(5))。

如何才能达到之前的结果,而只依靠组间的5s差异还考虑到交叉

编辑:正如 Ben 所建议的,这是我的数据框 df[1:20,]dput()

structure(list(PacketTime = c(7.083779, 7.147268, 7.147462, 12.084768, 
12.153246, 12.153951, 17.095972, 17.159268, 17.159876, 22.11384, 
22.176926, 22.177467, 27.134427, 27.199108, 27.200064, 32.144442, 
32.208648, 32.20922, 37.144255, 37.205622), FrameLen = c(304L, 
276L, 276L, 304L, 276L, 276L, 304L, 276L, 276L, 304L, 276L, 276L, 
304L, 276L, 276L, 304L, 276L, 276L, 304L, 276L), IPLen = c(300L, 
272L, 272L, 300L, 272L, 272L, 300L, 272L, 272L, 300L, 272L, 272L, 
300L, 272L, 272L, 300L, 272L, 272L, 300L, 272L), TCPLen = c(260L, 
232L, 232L, 260L, 232L, 232L, 260L, 232L, 232L, 260L, 232L, 232L, 
260L, 232L, 232L, 260L, 232L, 232L, 260L, 232L), Movement = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names = c(NA, 
20L), class = "data.frame")

【问题讨论】:

  • 请先使用dput()分享您的一些数据...
  • @Ben 更新了 OP 以包含 dput()

标签: r dataframe


【解决方案1】:

这是使用 aggregate+ transform 的基本 R 解决方案

u <- aggregate(
    . ~ PacketTime,
    transform(df,
        PTime = ave(PacketTime, trunc(PacketTime), 
        FUN = function(x) diff(range(x))), PacketTime = trunc(PacketTime)
    ),
    c
)
dfout <- transform(u, PTime = sapply(PTime, unique))

给了

> dfout
  PacketTime      FrameLen         IPLen        TCPLen Movement    PTime
1          7 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.063683
2         12 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.069183
3         17 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.063904
4         22 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.063627
5         27 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.065637
6         32 304, 276, 276 300, 272, 272 260, 232, 232  0, 0, 0 0.064778
7         37      304, 276      300, 272      260, 232     0, 0 0.061367

【讨论】:

    【解决方案2】:

    一种方法是使用seqcut。每 5 秒创建一个从最小到最大时间的序列。然后,使用cut 将您的时间间隔。您可以使用标签的间隔,例如:(7-12 秒)通过省略 labels 参数。或者只使用间隔中较短的时间(7 秒),如下所示。

    library(tidyverse)
    
    my_breaks <- seq(trunc(min(packets$PacketTime)), max(packets$PacketTime) + 5, 5)
    packets$Interval <- cut(packets$PacketTime, breaks = my_breaks, labels = my_breaks[-length(my_breaks)], right = FALSE)
    
    packets %>%
      group_by(Interval) %>%
      summarise(
        PTime=max(PacketTime)-min(PacketTime),
        FLen=list(FrameLen),
        ILen=list(IPLen),
        Movement=0
      ) %>%
      rename(PacketTime=PTime) %>%
      rename(FrameLen=FLen) %>%
      rename(IPLen=ILen)
    

    输出

    # A tibble: 7 x 5
      Interval PacketTime FrameLen  IPLen     Movement
      <fct>         <dbl> <list>    <list>       <dbl>
    1 7            0.0637 <int [3]> <int [3]>        0
    2 12           0.0692 <int [3]> <int [3]>        0
    3 17           0.0639 <int [3]> <int [3]>        0
    4 22           0.0636 <int [3]> <int [3]>        0
    5 27           0.0656 <int [3]> <int [3]>        0
    6 32           0.0648 <int [3]> <int [3]>        0
    7 37           0.0614 <int [2]> <int [2]>        0
    

    【讨论】:

    • 感谢您的回答!您能否更深入地解释一下您对前两个变量所做的工作?以便其他可能偶然发现此问题的用户能够理解结果是什么!
    • 另请注意 - 我在左侧添加了right = FALSE 如此接近的间隔(意思是大于或等于 7 秒,而不是仅大于 7 秒 - 尽管这可能无关紧要.. .)
    • @rshah 也可以使用trunc 代替round,这样可以确保7.8 秒从7 秒而不是8 秒开始...
    猜你喜欢
    • 2020-01-11
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多