![](/img/trans.png)
[英]How to transform a nested for-loop operation to a more efficient code in R
[英]how to write a more efficient code for this nested for-loop in R?
嘗試計算p1
(實驗組中的事件)和p0
(對照組中的事件)的組合, or
(優勢比)為1.5
。 nnt
= 需要治療的數量 (100/( p1
- p0
))
library(tidyverse)
p1 <- seq(0,1, 0.0001)
p0 <- seq(0,1,0.0001)
or <- 1.5
df <- tibble(p1 = as.numeric(), p0 = as.numeric(), nnt = as.numeric())
for (i in p1) {
for (j in p0) {
or_formula <- round((i/(1-i))/(j/(1-j)),3)
if (or_formula == or & !is.na(or_formula)) {
df <- df %>% add_row(p1 = i, p0 = j, nnt = round(1/(i-j), digits = 0))
}
}
}
我們可以使用outer
or_formula <- function(i, j) round((i/(1-i))/(j/(1-j)), 3)
m1 <- outer(p1, p0, FUN = or_formula)
dim(m1)
#[1] 10001 10001
i1 <- m1 == or & !is.na(m1)
i2 <- which(i1, arr.ind = TRUE)
p1new <- p1[i2[,1]]
p0new <- p0[i2[,2]]
df1 <- tibble(p1 = p1new, p0 = p0new, nnt = round(1/(p1new-p0new), digits = 0))
- 使用外部
system.time({
m1 <- outer(p1, p0, FUN = or_formula)
i1 <- m1 == or & !is.na(m1)
i2 <- which(i1, arr.ind = TRUE)
p1new <- p1[i2[,1]]
p0new <- p0[i2[,2]]
df1 <- tibble(p1 = p1new, p0 = p0new, nnt = round(1/(p1new-p0new), digits = 0))
})
# user system elapsed
# 5.038 1.288 6.319
- 使用 OP 的 for 循環
system.time({
df <- tibble(p1 = as.numeric(), p0 = as.numeric(), nnt = as.numeric())
for (i in p1) {
for (j in p0) {
or_formula <- round((i/(1-i))/(j/(1-j)),3)
if (or_formula == or & !is.na(or_formula)) {
df <- df %>% add_row(p1 = i, p0 = j, nnt = round(1/(i-j), digits = 0))
}
}
}
})
# user system elapsed
#122.391 0.748 123.128
- 測試相等性
identical(df, df1)
#[1] TRUE
這是另一個帶有expand.grid
+ subset
的基本 R 選項(但不如@akurn 的outer
解決方案快)
na.omit(
subset(
transform(
expand.grid(p1 = p1, p0 = p0),
nnt = round(1 / (p1 - p0), 0),
),
round((p1 / (1 - p1)) / (p0 / (1 - p0)), 3) == or
)
)
dplyr/purrr 方法:
library(tidyverse)
p1 <- seq(0,1, 0.0001)
p0 <- seq(0,1,0.0001)
or <- 1.5
test <- map_df(p1, function(p1_element){
map( p1_element,
~list(
p_0 = p0,
p_1 = p1_element,
or_formula = (. / (1-.)) / (p0 / (1 - p0)) ) ) }) %>%
mutate(or_formula = round(or_formula, 3)) %>%
filter(!is.na(or_formula) & or_formula == or) %>%
mutate(nnt = round(1 / (p_1 - p_0), digits = 0))
test %>% select(-or_formula)
## 6.531 sec elapsed
## original for loop : 131.454 sec elapsed
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.