【问题标题】:Subset using minimum number of values positioned around maximum value使用位于最大值附近的最小数量值的子集
【发布时间】:2019-02-28 10:59:40
【问题描述】:

情况:我有一个由不同记录器收集的数据集列表,如下所示:

df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                                  1L, 1L, 1L, 1L, 1L), .Label = "logger1", class = "factor"), OriginalTraitValue = c(0.37968, 
                                                                                                                     0.455131, 0.606376, 0.910194, 1.19499, 1.55612, 1.91735, 2.35493, 
                                                                                                                     2.60147, 2.42803, 1.66277, 1.12656, 0.628537), Temp = c(11.7334, 
                                                                                                                                                                             14.627, 19.3428, 24.5959, 29.6344, 34.7809, 39.606, 44.5389, 
                                                                                                                                                                             49.7914, 54.8254, 59.6391, 64.6695, 69.7002)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                                -13L))

任务:我只想保留在max(OriginalTraitValue) 之前和之后至少记录两个Temp 值的数据集。

我希望这个情节更清楚。红色 = 最大值,绿色 = 保留数据集所需的值。


问题

如何在 R 中执行此操作,例如使用dplyr?

我已经设法使用df$Temp[df$OriginalTraitValue == max(df$OriginalTraitValue)] 识别出与max(OriginalTraitValue) 对应的Temp 值,但我正在努力使用必要的位置参数来过滤数据集。

编辑

上面的例子代表了一个我想保留的数据集。完整的数据集如下所示:

    df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L), .Label = c("logger1", "logger2", "logger3"
), class = "factor"), OriginalTraitValue = c(3.36e-11, 3.68e-11, 
5.12e-11, 6.24e-11, 6.72e-11, 8.64e-11, 1.04e-10, 1.1e-10, 1.18e-10, 
90.34189, 86.332214, 108.00114, 111.190155, 114.34427, 135.1673, 
139.18198, 142.76979, 145.09233, 0.002, 0.06, 0.07, 0.15, 0.17, 
0.17, 0.18, 0.18, 0.15, 0.07, 0.09), Temp = c(16, 18, 20, 22, 
24, 26, 28, 30, 32, 16.726307, 17.376368, 20.193129, 25.06135, 
25.060663, 29.875113, 29.924177, 30.422773, 34.417274, 10, 12.5, 
15, 18, 20, 22.5, 25, 27.5, 30, 32.5, 35)), class = "data.frame", row.names = c(NA, 
-29L))

> summary(df)
       ID     OriginalTraitValue      Temp      
 logger1: 9   Min.   :  0.00     Min.   :10.00  
 logger2: 9   1st Qu.:  0.00     1st Qu.:18.00  
 logger3:11   Median :  0.15     Median :25.00  
              Mean   : 37.02     Mean   :23.90  
              3rd Qu.: 90.34     3rd Qu.:29.92  
              Max.   :145.09     Max.   :35.00  

在这个数据集中,我只会将ID 保留为logger3,因为只有logger3max(OriginalTraitValue) 之前和之后包含至少2 个值。

【问题讨论】:

  • 你的预期输出是什么?
  • 我编辑了我的问题以使其更清楚。预期的输出是一个代码,如果在收集最大值之前和之后少于 2 个值(按一个 ID)

标签: r dplyr subset


【解决方案1】:

试试:

library(dplyr)

df %>%
  group_by(ID) %>%
  slice(which.max(OriginalTraitValue) + -2:2) %>%
  filter(n() == 5)

输出:

# A tibble: 5 x 3
# Groups:   ID [1]
  ID      OriginalTraitValue  Temp
  <fct>                <dbl> <dbl>
1 logger1               1.92  39.6
2 logger1               2.35  44.5
3 logger1               2.60  49.8
4 logger1               2.43  54.8
5 logger1               1.66  59.6

如果您想过滤整个组,而不仅仅是问题中的 5 个观察值,您还可以执行以下操作:

df %>%
  group_by(ID) %>%
  filter(any(cumsum(row_number() %in% c(which.max(OriginalTraitValue) + -2:2)) == 5))

【讨论】:

  • 谢谢!我可以使用它来识别我想要的ID,然后将整个数据框作为子集。
  • 不客气@Joris!查看我的编辑,我添加了一个解决方案,可以保留完整的数据框,因此您不需要额外的子集。
  • 像魅力一样工作!
【解决方案2】:

您可以使用 dplyr filter 实现这一目标

df %>%
  group_by(ID) %>%
  filter(abs(which(OriginalTraitValue == max(OriginalTraitValue)) - row_number()) <= 2)

  ID      OriginalTraitValue  Temp
  <fct>                <dbl> <dbl>
1 logger1               1.92  39.6
2 logger1               2.35  44.5
3 logger1               2.60  49.8
4 logger1               2.43  54.8
5 logger1               1.66  59.6

【讨论】:

  • 好主意。直觉的。 +1
  • 这将使条件minimum 2 values before and after 失败。在structure(list(ID = structure(c(1L, 1L), .Label = "logger2", class = "factor"), OriginalTraitValue = c(0.37968, 0.455131), Temp = c(11.7334, 14.627)), row.names = 1:2, class = "data.frame") 上试一试,它应该会删除这些值,但会保留它们。在filter 中添加类似n() == 5 的内容。
  • 感谢您的回复。我没有正确指定我的预期输出。我想我需要使用这种语法作为保留或删除特定 ID 的条件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 2013-03-26
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多