按因子计算值的比例

Compute proportion of values by factor

我有一个看起来像这样的数据框(18,000 行)。每行都有一个 p 值和一个“频率”。频率是一个从 0 到 31 的因子。

 > head(df)
                  Gene P.value Frequency
    3  ENSG00000000419  1.000         1
    9  ENSG00000001084  0.851         2
    12 ENSG00000001461  0.699         4
    26 ENSG00000002746  0.113        23
    28 ENSG00000002834  0.529        12
    33 ENSG00000003137  0.464        31

我如何创建一个新的数据帧来计算每个频率 P.values 的比例,即小于 0.01?

我希望结果如下所示:

> head(result_Df)

Frequency   Proportion
        0         0.02
        1         0.3
        2         0.02
        3         0.15

我认为 dplyr 做得相当快,但我对那个包没有经验。感谢您的帮助!

这里有一个方法:


library(data.table)
setDT(result_Df)
result_Df[ , .(Proportion = sum( P.value < .01 ) / .N ) , by=Frequency ]


注意有做事快,还有用尽可能少的代码行做事。

两者各有千秋,后者在基于dplyr的代码中肯定有文化。

data.table 写得很快,在这种情况下可能更可取。 (肯定也很短)

比较 18k 合成行的 dplyr 和 data.table 看起来像这样:


lirary(data.table)
library(microbenchmark)
set.seed(100)
n <- 18e3
synthetic_Df = data.frame(
    Gene = sprintf( "ENSG%011d", ceiling(runif( n, min=1, max=2e4 )) ),
    P.value = runif( n ),
    Frequency = ceiling( runif( n, min=1, max=30 ) )
)

dt <- as.data.table(synthetic_Df)

microbenchmark(
    dplyr = synthetic_Df %>% group_by( Frequency ) %>% summarize( Proporion = sum( P.value < .01 ) / n() ),
    data.table = dt[ , .(Proportion = sum( P.value < .01 ) / .N) , by=Frequency ]
)


输出:


Unit: microseconds
       expr      min        lq      mean    median       uq      max neval cld
      dplyr 2004.720 2052.8060 2123.1076 2070.6640 2106.617 4793.772   100   b
 data.table  833.253  856.5115  915.5324  876.6245  904.607 3659.965   100  a 

data.table 快了 2.5 倍。这并不意味着 dplyr 方法在这种情况下不够好,很可能是这样。

使用 dplyr 的一种方式。将 1 分配给 P.value < 0.01 的情况,求和并除以每组的总行数。

library(dplyr)

df1 %>%
  group_by(Frequency) %>%
  summarise(Proportion = sum(ifelse(P.value < 0.01, 1, 0)) / n())

示例数据和结果:

df1 <- data.frame(Frequency = c(1,1,1,2,2,2),
                  P.value = c(0.001, 0.1, 0.2, 0.007, 0.009, 0.01))

# A tibble: 2 x 2
  Frequency Proportion
      <dbl>      <dbl>
1         1      0.333
2         2      0.667