使用向下应用行时的 R 参考列
R reference column while using apply down rows
如果我有一些可以建模的数据:
c1 <- c("A","B","C","A")
c2 <- c("a", "a", "b", "c")
c3 <- c(0, 1, 0, 0)
c4 <- c(0, 0, 0, 1)
c5 <- c(1, 0, 0, 0)
df <- data.frame(c1 = c1, c2 = c2, c3 = c3, c4 = c4, c5 = c5)
我想要一个数组 array.filled
,对于 3:5 列,如果 0
则从 c1
填充,如果 1
则从 c2
填充。
我正在考虑使用 apply
和 ifelse
来执行此操作,但不知道如何使用 apply(df, 2, function(x), ifelse(x == 0, ?, x))
来引用列(在这种情况下我会这样做两次)。
关于ifelse()
ifelse
的基本用法如下:
ifelse(c3 == 0, c1, c2) ## ifelse(condition, if(TRUE), if(FALSE))
如果c3 == 0
需要c1
;否则需要 c2
。您还可以查看 ?ifelse
了解更多。
使用apply()
要将此应用到 df[, 3:5]
,请执行:
foo <- function(x, opt0, opt1) ifelse(x == 0, opt0, opt1)
array.filled <- apply(df[, 3:5], 2, foo, opt0 = df[, 1], opt1 = df[, 2])
# c3 c4 c5
#[1,] "A" "A" "a"
#[2,] "a" "B" "B"
#[3,] "C" "C" "C"
#[4,] "A" "c" "A"
使用sapply()
alternative/better 方法是使用 sapply
:
# still using the `foo` defined above
array.filled <- sapply(df[3:5], foo, opt0 = df$c1, opt1 = df$c2)
# c3 c4 c5
#[1,] "A" "A" "a"
#[2,] "a" "B" "B"
#[3,] "C" "C" "C"
#[4,] "A" "c" "A"
在使用上面接受的答案时,以下内容也适用于我的真实数据:
my.array.filled <- apply(df[, 3:5], 2, function(x) ifelse(x == 0, df$c1, df$c2))
它显然是一样的,但可能更容易阅读。
使用矩阵索引并避免可能代价高昂的循环:
sel <- cbind(seq(1,nrow(df)), unlist(df[3:5]+1, use.names=FALSE, recursive=FALSE))
replace(df[3:5], TRUE, df[1:2][sel])
# c3 c4 c5
#1 A A a
#2 a B B
#3 C C C
#4 A c A
这基本上在 sel
中存储了一个 row/column 索引,用于从 df[1:2]
中提取适当的值,然后用于覆盖 [=] 中已经存在的值13=]
它会更快,但当然,如果您只有相对较小的数据集,那可能没有任何问题。通过我的测试,其他两个答案 运行 在合理的时间内,直到您获得 10M 记录量级的非常大的数据。
如果我有一些可以建模的数据:
c1 <- c("A","B","C","A")
c2 <- c("a", "a", "b", "c")
c3 <- c(0, 1, 0, 0)
c4 <- c(0, 0, 0, 1)
c5 <- c(1, 0, 0, 0)
df <- data.frame(c1 = c1, c2 = c2, c3 = c3, c4 = c4, c5 = c5)
我想要一个数组 array.filled
,对于 3:5 列,如果 0
则从 c1
填充,如果 1
则从 c2
填充。
我正在考虑使用 apply
和 ifelse
来执行此操作,但不知道如何使用 apply(df, 2, function(x), ifelse(x == 0, ?, x))
来引用列(在这种情况下我会这样做两次)。
关于ifelse()
ifelse
的基本用法如下:
ifelse(c3 == 0, c1, c2) ## ifelse(condition, if(TRUE), if(FALSE))
如果c3 == 0
需要c1
;否则需要 c2
。您还可以查看 ?ifelse
了解更多。
使用apply()
要将此应用到 df[, 3:5]
,请执行:
foo <- function(x, opt0, opt1) ifelse(x == 0, opt0, opt1)
array.filled <- apply(df[, 3:5], 2, foo, opt0 = df[, 1], opt1 = df[, 2])
# c3 c4 c5
#[1,] "A" "A" "a"
#[2,] "a" "B" "B"
#[3,] "C" "C" "C"
#[4,] "A" "c" "A"
使用sapply()
alternative/better 方法是使用 sapply
:
# still using the `foo` defined above
array.filled <- sapply(df[3:5], foo, opt0 = df$c1, opt1 = df$c2)
# c3 c4 c5
#[1,] "A" "A" "a"
#[2,] "a" "B" "B"
#[3,] "C" "C" "C"
#[4,] "A" "c" "A"
在使用上面接受的答案时,以下内容也适用于我的真实数据:
my.array.filled <- apply(df[, 3:5], 2, function(x) ifelse(x == 0, df$c1, df$c2))
它显然是一样的,但可能更容易阅读。
使用矩阵索引并避免可能代价高昂的循环:
sel <- cbind(seq(1,nrow(df)), unlist(df[3:5]+1, use.names=FALSE, recursive=FALSE))
replace(df[3:5], TRUE, df[1:2][sel])
# c3 c4 c5
#1 A A a
#2 a B B
#3 C C C
#4 A c A
这基本上在 sel
中存储了一个 row/column 索引,用于从 df[1:2]
中提取适当的值,然后用于覆盖 [=] 中已经存在的值13=]
它会更快,但当然,如果您只有相对较小的数据集,那可能没有任何问题。通过我的测试,其他两个答案 运行 在合理的时间内,直到您获得 10M 记录量级的非常大的数据。