【问题标题】:Calculate for all columns in R计算 R 中的所有列
【发布时间】:2019-07-02 10:14:34
【问题描述】:

我有一个 data.frame 如下。对于每一列,如果值在 2.5% (>=) [倒数第二列] 和 97.5% (

> df
              S1    S2    S3    S4    S5    S6    2.5%  97.5%
Gene1         0.02  0.04  0.05  0.03  0.10  0.06  0.01  0.08
Gene1         0.04  0.04  0.04  0.06  0.03  0.04  0.03  0.09
Gene1        51.00 57.00  50.00 54.00 70.00 63.00 41.00 71.00
Gene1         0.46  0.35  0.28  0.41  0.26  0.29  0.21  0.45
Gene1         0.09  0.08  0.09  0.09  0.08  0.09  0.07  0.10
Gene1        46.80 44.60  48.40 45.30 40.90 46.10 36.69 49.20
Gene1           NA    NA  20.30 14.10 12.10 15.50  8.72 25.61
Gene1         1.96  1.05  1.39  1.56  1.54  1.71  1.24  2.00
Gene1         0.53  0.52  0.61  0.83  0.73  0.37  0.36  0.91
Gene1         1.05  0.55  0.85  1.30  1.14  0.64  0.61  1.39
Gene1        22.31 28.88  26.75 25.08 26.29 23.34 19.76 33.44

所以最后,我想要一个看起来像这样的 data.frame。

> df_updated
              S1  S2  S3  S4  S5  S6
Gene1         1   1   1   1   2   1
Gene1         1   1   1   1   1   1
Gene1         1   1   1   1   1   1
Gene1         2   1   1   1   1   1
Gene1         1   1   1   1   1   1
Gene1         1   1   1   1   1   1
Gene1        NA  NA   1   1   1   1
Gene1         1   2   1   1   1   1
Gene1         1   1   1   1   1   1
Gene1         2   2   1   1   1   1
Gene1         1   1   1   1   1   1

我尝试了以下类似的方法,但最终出现错误。我从这里 (Error in if/while (condition) {: missing Value where TRUE/FALSE needed) 了解到,这与我在矩阵中的 NA 有关,但我不确定如何通过代码来适应它,并获得我想要的数据帧 'df_updated'。

df_updated <- as.data.frame(lapply(df, function(x) if (x>=df$`2.5%` & x<=df$`97.5%`) {x==1} else {x==2}))

Error in if (x >= df$`2.5%` & x <= df$`97.5%`) { : 
  missing value where TRUE/FALSE needed
In addition: There were 50 or more warnings (use warnings() to see the first 50)

任何帮助表示赞赏。 谢谢。

【问题讨论】:

  • 你确定你有data.frame吗?鉴于您有重复的行名,这看起来可能是matrix。你能在这里dput(df) 让我们确切地知道你在做什么吗?

标签: r multiple-columns na


【解决方案1】:

要测试您的值是否在分位数范围内,您可以在 apply 内使用 ifelse,例如:

df <- read.table(header=TRUE, text="
x             S1    S2    S3    S4    S5    S6    x2.5  x97.5
Gene1         0.02  0.04  0.05  0.03  0.10  0.06  0.01  0.08
Gene1         0.04  0.04  0.04  0.06  0.03  0.04  0.03  0.09
Gene1        51.00 57.00  50.00 54.00 70.00 63.00 41.00 71.00
Gene1         0.46  0.35  0.28  0.41  0.26  0.29  0.21  0.45
Gene1         0.09  0.08  0.09  0.09  0.08  0.09  0.07  0.10
Gene1        46.80 44.60  48.40 45.30 40.90 46.10 36.69 49.20
Gene1           NA    NA  20.30 14.10 12.10 15.50  8.72 25.61
Gene1         1.96  1.05  1.39  1.56  1.54  1.71  1.24  2.00
Gene1         0.53  0.52  0.61  0.83  0.73  0.37  0.36  0.91
Gene1         1.05  0.55  0.85  1.30  1.14  0.64  0.61  1.39
Gene1        22.31 28.88  26.75 25.08 26.29 23.34 19.76 33.44")

t(apply(df[-1], 1, function(x) ifelse(x>=x[length(x)-1] & x<=x[length(x)], 1, 2)))[,1:6]
#      S1 S2 S3 S4 S5 S6
# [1,]  1  1  1  1  2  1
# [2,]  1  1  1  1  1  1
# [3,]  1  1  1  1  1  1
# [4,]  2  1  1  1  1  1
# [5,]  1  1  1  1  1  1
# [6,]  1  1  1  1  1  1
# [7,] NA NA  1  1  1  1
# [8,]  1  2  1  1  1  1
# [9,]  1  1  1  1  1  1
#[10,]  1  2  1  1  1  1
#[11,]  1  1  1  1  1  1

【讨论】:

    【解决方案2】:

    不要认为您需要sapply/lapply 或任何类型的循环。您可以直接将数据框中的值与列进行比较。除了可以使用replace 转换的FALSE 值之外,您将获得预期的输出。

    cols <- c(ncol(df) - 1, ncol(df))
    df_updated <- df[-cols] >= df[[cols[1]]] & df[-cols] <= df[[cols[2]]]
    df_updated <- replace(df_updated, !df_updated, 2)
    
    #      S1 S2 S3 S4 S5 S6
    # [1,]  1  1  1  1  2  1
    # [2,]  1  1  1  1  1  1
    # [3,]  1  1  1  1  1  1
    # [4,]  2  1  1  1  1  1
    # [5,]  1  1  1  1  1  1
    # [6,]  1  1  1  1  1  1
    # [7,] NA NA  1  1  1  1
    # [8,]  1  2  1  1  1  1
    # [9,]  1  1  1  1  1  1
    #[10,]  1  2  1  1  1  1
    #[11,]  1  1  1  1  1  1
    

    此外,如果您需要最终输出作为数据框,您可以将其包装在最后的 data.frame() 中。


    @thelatemail 建议的智能单线是

    (df[-cols] < df[["2.5%"]] | df[-cols] > df[["97.5%"]]) + 1
    

    【讨论】:

    • 对我来说太快了——这是我的类似逻辑的变体 2 分钟太慢了——vars &lt;- paste0("S",1:6); (dat[vars] &lt; dat[["2.5%"]] | dat[vars] &gt; dat[["97.5%"]]) + 1
    • @thelatemail 很聪明。我试图将它挤成一条线,但没有成功。
    • 在简化之前我进行了几次尝试 ;-) 需要 2/1 顺序意味着进行相反的比较 &lt; | &gt; 而不是 &gt;= &amp; &lt;=,但希望核心思想仍然清晰。跨度>
    猜你喜欢
    • 1970-01-01
    • 2016-03-22
    • 2022-12-09
    • 1970-01-01
    • 2014-06-29
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多