[英]Using nested apply functions instead of nested for loops
我的目標是迭代df
中的每一列,然后針對每一列向下迭代每一行並執行一個函數。 在這種情況下,特定功能將NA
值替換為最后一列中的相應值,但是所需功能的詳細信息與此處的問題無關。 我得到了使用兩個嵌套的for循環所需的結果,如下所示:
for (j in 1:ncol(df.i)) {
for (i in 1:nrow(df.i)) {
df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
}
}
不過,我相信這應該使用有可能apply(df.i, 1, function)
嵌套的內部apply(df.i, 2, function)
,但我不能完全肯定這是可能的,或者怎么做的。 有誰知道如何通過apply
函數來實現同一目標?
這是執行內部指令的四種方法。
首先,一個數據集示例。
set.seed(5345) # Make the results reproducible
df.i <- matrix(1:400, ncol = 40)
is.na(df.i) <- sample(400, 50)
現在,@ Dave2e的注釋:僅一個for
循環,矢量化最里面的一個。
df.i2 <- df.i3 <- df.i1 <- df.i # Work with copies
for (j in 1:ncol(df.i1)) {
df.i1[,j] <- ifelse(is.na(df.i1[, j]), df.i1[, 39], df.i1[, j])
}
然后,進行矢量化處理, 完全沒有循環 。
df.i2 <- ifelse(is.na(df.i), df.i[, 39], df.i)
@Gregor在評論中對另一個向量進行了矢量化,這要好得多,因為已知ifelse
相對較慢。
df.i3[is.na(df.i3)] <- df.i3[row(df.i3)[is.na(df.i3)], 39]
和您的解決方案,如問題中所述。
for (j in 1:ncol(df.i)) {
for (i in 1:nrow(df.i)) {
df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
}
}
比較結果。
identical(df.i, df.i1)
#[1] TRUE
identical(df.i, df.i2)
#[1] TRUE
identical(df.i, df.i3)
#[1] TRUE
基准。
@Gregor發表評論后,我決定對這4個解決方案進行基准測試。 不出所料,每次優化都會產生明顯的滲漏,並且他的完全矢量化解決方案是最快的。
f <- function(df.i){
for (j in 1:ncol(df.i)) {
for (i in 1:nrow(df.i)) {
df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
}
}
df.i
}
f1 <- function(df.i1){
for (j in 1:ncol(df.i1)) {
df.i1[,j] <- ifelse(is.na(df.i1[, j]), df.i1[, 39], df.i1[, j])
}
df.i1
}
f2 <- function(df.i2){
df.i2 <- ifelse(is.na(df.i2), df.i2[, 39], df.i2)
df.i2
}
f3 <- function(df.i3){
df.i3[is.na(df.i3)] <- df.i3[row(df.i3)[is.na(df.i3)], 39]
df.i3
}
microbenchmark::microbenchmark(
two_loops = f(df.i),
one_loop = f1(df.i1),
ifelse = f2(df.i2),
vectorized = f3(df.i3)
)
#Unit: microseconds
# expr min lq mean median uq max neval
# two_loops 1125.017 1143.4995 1226.93089 1152.5665 1190.599 5209.431 100
# one_loop 492.945 500.7045 518.73060 504.9435 516.638 678.951 100
# ifelse 42.269 45.7770 50.55519 48.4140 50.470 198.533 100
#vectorized 12.626 14.5520 16.21975 15.6380 17.663 27.525 100
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.