按因子计算值的比例
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
我有一个看起来像这样的数据框(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