如何根据为行子集指定的阈值对列进行子集化

How to subset columns based on threshold values specified for a subset of rows

我想对遵守此规则的大数据框的列进行子集化:

对于每个行(除了行A)值应该低于5。

给定以下示例数据框,我希望函数 return 具有 列 c1 的数据框,因为行 B:E 中的所有值都低于 5 .我认为 select_if 函数可能是要走的路,但我不知道如何排除该函数中的特定行。

Gene <- c("A", "B", "C", "D", "E")
c1 <- c(500, 1, 0, 3, 0)
c2 <- c(240, 235, 270, 100, 1)
c3 <- c(0, 3, 1000, 900, 2)
df1 <- data.frame(Gene, c1, c2, c3)
head(df1)

  Gene  c1  c2   c3
1    A 500 240    0
2    B   1 235    3
3    C   0 270 1000
4    D   3 100  900
5    E   0   1    2

基本的 R 解决方案易于编码。

i <- sapply(df1[-1], \(x) all(x[-1] < 5))
df1[c(TRUE, i)]
#>   Gene  c1
#> 1    A 500
#> 2    B   1
#> 3    C   0
#> 4    D   3
#> 5    E   0

reprex package (v2.0.1)

于 2022-06-03 创建

一个 tidyverse 解决方案是

df1 %>% 
  select(
    df1 %>% 
      filter(row_number() > 1) %>% 
      summarise(across(starts_with("c"), max)) %>% 
      pivot_longer(everything()) %>% 
      filter(value < 5) %>% 
      pull(name)
  )
   c1
1 500
2   1
3   0
4   3
5   0

说明:select中的代码在忽略第一行后计算每一列的最小值。然后将结果 pivot 编辑成长格式,创建默认列 namevalue。此数据框仅过滤为 select 每个值都小于 5 的那些列。然后 name 列被 pulled 并用作外部 select.

的参数

如果需要其他列,只需修改select即可,例如

df1 %>% 
  select(
    c("Gene", 
    df1 %>% 
      filter(row_number() > 1) %>% 
      summarise(across(starts_with("c"), max)) %>% 
      pivot_longer(everything()) %>% 
      filter(value < 5) %>% 
      pull(name)
  )
)

为避免整形或循环,请使用 colSums

df1[c(1, which(colSums(df1[-1, -1] < 5) == 4) + 1)]
#   Gene  c1
# 1    A 500
# 2    B   1
# 3    C   0
# 4    D   3
# 5    E   0