【问题标题】:Filter rows out with specific value for each sample column为每个样本列过滤出具有特定值的行
【发布时间】:2020-11-11 21:23:50
【问题描述】:

在至少三个样本中保留 Obs 值超过样本阈值的行 (Obs)。删除 2 或更少的行。

即。

  • Obs 1 只有 S5 超过阈值,因此将被过滤掉;
  • Obs2 有 4 个,Obs 3 有 3 个,因此它们将保留在 df 中。

.

df <- data.frame(column=c("threshold", "Obs1", "Obs2", "Obs3"), S1 = c(1.7,1.4,1.9,1.3), S2= c(0.9,0.8,2,1), S3=c(2.5,2.4,2.1,0.5), S4=c(0.4,0.5,0.6,0.9), S5=c(1.2,1.4,1.3,1.6))
 df

    column      S1  S2  S3  S4  S5
    threshold  1.7 0.9 2.5 0.4 1.2 
    Obs1       1.4 0.8 2.4 0.5 1.4 
    Obs2       1.9 2.0 2.1 0.6 1.3
    Obs3       1.3 1.0 0.5 0.9 1.6

期望的输出:

column      S1  S2  S3  S4  S5
 
Obs2       1.9 2.0 2.1 0.6 1.3
Obs3       1.3 1.0 0.5 0.9 1.6

我不知道如何编码,但我想知道是否使用这样的逻辑:

logic <- if df (S1-5)>= threshold value then =1; if df (S1-5) < threhold then = 0 

library(dplyr)
logic  %>% rowwise %%
    filter(sum(c_across(where(is.numeric))) >= 3) %>%
    ungroup

【问题讨论】:

  • df 的第一行叫做“threshold”,包含每列的阈值

标签: r dplyr


【解决方案1】:

如果我们使用rowwisec_across,只需slice 没有“阈值”行的行,然后将&gt; 与相应的sliced 数据集与“阈值”行进行比较

library(dplyr)
df %>% 
    slice(-1) %>% 
    rowwise %>%
    filter(sum(c_across(where(is.numeric)) 
                > 
                  (df %>% 
                      slice(1) %>%
                   select(-1))) >=3) %>%
    ungroup

-输出

# A tibble: 2 x 6
#  column    S1    S2    S3    S4    S5
#  <chr>  <dbl> <dbl> <dbl> <dbl> <dbl>
#1 Obs2     1.9     2   2.1   0.6   1.3
#2 Obs3     1.3     1   0.5   0.9   1.6

如果还有其他字符列,我们可以将select更改为子集数据

df  %>% 
   slice(-1) %>%
   rowwise %>% 
   filter(sum(c_across(where(is.numeric)) > df %>%
             slice(1) %>%
             select(where(is.numeric))) >=3)

或者map的另一个选项

library(purrr)
library(magrittr)
i1 <- map(df %>%
              select(where(is.numeric)),  ~ .x[-1] >  first(.x)) %>% 
        reduce(`+`) %>% 
        is_greater_than(2)
df %>% 
     slice(-1) %>% 
     filter(i1)

或者使用base RrowSums

df[-1,][rowSums(df[-1, -1] > df[1, -1][col(df[-1, -1])]) >=3,]
#  column  S1 S2  S3  S4  S5
#3   Obs2 1.9  2 2.1 0.6 1.3
#4   Obs3 1.3  1 0.5 0.9 1.6

【讨论】:

  • 谢谢,它们都有效,但我也想了解它们。对于选项(1- dplyr),什么功能稳定了“大于阈值”?对于选项(2-map),is_greater_than(2) 是否意味着大于第 2 行中的值?对于(3-base),您在哪里说“如果大于阈值,则给出 1 的值?。抱歉有很多问题,但我想学习!谢谢@akrun
  • @Ecg 对于选项 1,我们首先对行进行子集,因为它是逐行的。因此,具有阈值行数据的行直接在内部传递以执行对应的&gt;c_across 即(df %&gt;% slice(1) %&gt;% select(-1)) 和阈值通过&gt;=3 完成。在第二种情况下,我们正在循环数字列使用map,对第一个元素进行子集化并与其余元素进行比较,创建一个索引('i1')并使用它来对行进行子集化。
  • 完美,谢谢,请仔细阅读并尝试理解。 !
  • 我发现包含我的数据的代码不起作用,因为我的“阈值”是十进制的,而其他值不是。所以代码不能用这样的东西: 我可以取消阈值是十进制的事实吗?
  • @Ecg 当你说它不起作用时不清楚。我试过你的例子,它对我有用
【解决方案2】:

供将来参考: 如果您使用字符列,则需要确保具有值的列是数字的,如果不是,请转换它们

df <- type.convert(df, as.is = TRUE) 

然后,这应该可以工作

df2 <- df %>% slice(-1) %>% rowwise %>% filter(sum(c_across(where(is.numeric)) > (df %>%slice(1))) >=3)

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2018-12-08
    • 2015-04-07
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多