【问题标题】:Grouping values with condition使用条件对值进行分组
【发布时间】:2018-05-19 11:37:14
【问题描述】:

假设我有以下排序数据:

[1] 0.06997360 0.09154285 0.10607553 0.10607631 0.10652390 0.10857691
[7] 0.10858633 0.10858633 0.10870369 0.18790912 0.18792473 0.19509030
[13] 0.20040993 0.22548593 0.22550167 0.22593338 0.22893103 0.23196562
[19] 0.25901025 0.30231663 0.30245132 0.30246287 0.34893528 0.34938294
[25] 0.34943865 0.45200544 0.45658957 0.45673815 0.46432602 0.48493226
[31] 0.58318915 0.58618472 0.66311458 0.66311774 0.69777062 0.69782017
[37] 0.70456743 0.70754232 0.71668759 0.71744870 0.71780786 0.77227751
[43] 0.79785928 0.79823416 0.79831632 0.79832545 0.79863813 0.79880086
[49] 0.91610076 0.91611498 0.91611830 0.91612582 0.91612582 0.91614856

现在我想对它们进行分组,因为它们中的许多几乎相等。假设两个值 x[i] 和 x[i+1] 在一组中的条件是 if (x[i+1]-x[i]

【问题讨论】:

    标签: r if-statement grouping conditional-statements sequence


    【解决方案1】:

    这里是如何做到这一点。我按组使用dplyrsummarise。首先,我使用滞后 1 计算差异向量。然后,我创建一个条件列,如果 diff > 0.01 则为 1,否则为 0。然后,我使用cumsum 分组。 coalesce 用于处理开头的NA。使用这些组,您现在可以summarise

    x <- c(0.06997360, 0.09154285, 0.10607553, 0.10607631, 0.10652390, 0.10857691,
    0.10858633,0.10858633,0.10870369,0.18790912,0.18792473,0.19509030,
    0.20040993,0.22548593,0.22550167,0.22593338,0.22893103,0.23196562,
    0.25901025,0.30231663,0.30245132,0.30246287,0.34893528,0.34938294,
    0.34943865,0.45200544,0.45658957,0.45673815,0.46432602,0.48493226,
    0.58318915,0.58618472,0.66311458,0.66311774,0.69777062,0.69782017,
    0.70456743,0.70754232,0.71668759,0.71744870,0.71780786,0.77227751,
    0.79785928,0.79823416,0.79831632,0.79832545,0.79863813,0.79880086,
    0.91610076,0.91611498,0.91611830,0.91612582,0.91612582,0.91614856)
    
    library(dplyr)
    as.data.frame(x)%>%
      mutate(diff=x-lag(x),
             condition=(diff>0.01)*1,
             group=cumsum(coalesce(condition, 0)))%>%
      group_by(group)%>%
      summarise(x_mean=mean(x))%>% 
      as.data.frame() 
    
       group     x_mean
    1      0 0.06997360
    2      1 0.09154285
    3      2 0.10758986
    4      3 0.19283352
    5      4 0.22756353
    6      5 0.25901025
    7      6 0.30241027
    8      7 0.34925229
    9      8 0.45741479
    10     9 0.48493226
    11    10 0.58468694
    12    11 0.66311616
    13    12 0.70852067
    14    13 0.77227751
    15    14 0.79836237
    16    15 0.91612237
    

    【讨论】:

    • 或者只是data.frame(vec) %&gt;% group_by(grp = cumsum(c(0, diff(vec) &gt; 0.01))) %&gt;% summarise(meanvec = mean(vec))
    • 非常感谢! cumsum 的绝妙主意!
    • 我更喜欢 data.table,这是我的解决方案(不知道如何将注释显示为代码,抱歉...):X % .[, diff := x - shift(x)] %>% .[is.na(diff), diff := 0] %>% .[, condition := diff > 0.01] %>% .[, group := 条件 %>% cumsum] %>% .[, x_mean := mean(x), group]
    【解决方案2】:

    在基数 R 中,您可以使用 tapply 返回命名向量,使用 diffcumsum 构造分组机制,如下所示

    tapply(x, cumsum(c(0, diff(x) > 0.01)), mean)
    

    返回

             0          1          2          3          4          5          6 
    0.06997360 0.09154285 0.10758986 0.19283352 0.22756353 0.25901025 0.30241027 
             7          8          9         10         11         12         13 
    0.34925229 0.45741479 0.48493226 0.58468694 0.66311616 0.70852067 0.77227751 
            14         15 
    0.79836237 0.91612237 
    

    你可以把它放在这样的data.frame中

    data.frame(groupMeans = tapply(x, cumsum(c(0, diff(x) > 0.01)), mean))
    

    正如 Jaap 在 cmets 中提到的,返回 data.frame 的更直接方法是使用 aggregate 围绕相同的分组机制。

    aggregate(vec, list(cumsum(c(0, diff(vec) > 0.01))), mean)
    

    这有一个很好的特性,分组向量作为一个变量包含在 data.frame 中。

    Ronak shah 的sapplysplit 是一种更明确的拆分数据并计算其均值的方法。 tapply 在“幕后”执行此操作。

    【讨论】:

    • aggregate(vec, list(cumsum(c(0, diff(vec) &gt; 0.01))), mean) (当我看到你的答案时正要发布)
    • 另外,sapply(split(x, cumsum(c(0,diff(x)) &gt; 0.01)), mean)
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2020-10-22
    • 2016-09-14
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多