如何根据R中的两个不同列删除或子集样本

时间:2021-06-17 22:14:09

标签: r for-loop

我有一个包含 1000 行的 df。简化后看起来像这样:

df1 <- data.frame(Sample = c('A1', 'B2', 'C3', 'A1', 'B2', 'C3','A1', 'B2', 'C3'),
                  Day = c('1', '3', '5', '4', '2', '6','5', '4', '2' ),
                  Value = c('0.1', '0.8', '0.7', '0.6', '0.3', '0.4', '0.4', '0.2', '0.3'))

我想删除在测量最大值后几天出现的样本。

我可以查看每个样本的最大值以及它们落在哪几天:

library(dplyr)
df2 <- df1 %>% 
             group_by(Value, Day, Sample) %>%
             slice(which.max(Value))

然后,如果我可以删除在测量最大值后几天发生的每个样本的行,我将获得所需的 df:

df3 <- data.frame(Sample = c('A1', 'B2', 'C3', 'A1', 'B2', 'C3'),
                                    Day = c('1', '3', '5', '4', '2','2' ),
                                    Value = c('0.1', '0.8', '0.7', '0.6', '0.3', '0.3'))

这似乎需要一个 for 循环,但我今天没有在很多气缸上开火,所以非常感谢任何帮助。 TIA。

2 个答案:

答案 0 :(得分:1)

示例数据创建时使用数字列作为 character(注意 '0.1' 而不是 0.1),因此我们使用 type.convert 自动转换列类型, arrange 按'Sample'、'Day' 的数据,然后按'Sample' 分组,得到'Value' 最大值的索引,加1 并删除(-) 带有{{ 的行1}}

slice

-输出

library(dplyr)
df1 %>%
     type.convert(as.is = TRUE) %>%
     arrange(Sample, Day) %>% 
     group_by(Sample) %>%
     slice(-(which.max(Value) + 1)) %>%
     ungroup

如果我们想去掉 # A tibble: 6 x 3 Sample Day Value <chr> <int> <dbl> 1 A1 1 0.1 2 A1 4 0.6 3 B2 2 0.3 4 B2 3 0.8 5 C3 2 0.3 6 C3 5 0.7 之后的所有行(在 maxing by 'Day', 'Sample' 之后)

arrange

或者将 df1 %>% type.convert(as.is = TRUE) %>% arrange(Sample, Day) %>% group_by(Sample) %>% filter(cumsum(cumsum(Value == max(Value, na.rm = TRUE))) <= 1) %>% ungroup slice 一起使用

seq

答案 1 :(得分:0)

使用 ave -

的基本 R 选项
df1 <- type.convert(df1, as.is = TRUE)
df1 <- df1[with(df1, order(Sample, Day)), ]

subset(df1, as.logical(ave(Value, Sample, 
            FUN = function(x) seq_along(x) <= match(max(x), x))))

#  Sample Day Value
#1     A1   1   0.1
#4     A1   4   0.6
#5     B2   2   0.3
#2     B2   3   0.8
#9     C3   2   0.3
#3     C3   5   0.7