Reputation: 765
How can I use one list of vectors to replace the values in another list of data frames? Ultimately, I want a data frame that has certain values replaced by NAs.
list1 <- list(1:2, 3:4, 5:6)
list2 <- as.list(data.frame(mat.or.vec(6, 3)))
desired_ouput <- data.frame(mat.or.vec(6, 3))
desired_ouput[1:2, 1] <- NA
desired_ouput[3:4, 2] <- NA
desired_ouput[5:6, 3] <- NA
desired_ouput
Upvotes: 1
Views: 391
Reputation: 73325
This may not look obvious, but is rather efficient (fully vectorized, with no for
loop or *apply
family)
y <- unlist(list2, use.names = FALSE); m <- length(list2[[1]])
x <- unlist(list1) + rep((0:(length(list1)-1)) * m, lengths(list1))
y[x] <- NA; attr(y, "dim") <- c(m, length(y) / m)
as.data.frame(y)
# V1 V2 V3
# 1 NA 0 0
# 2 NA 0 0
# 3 0 NA 0
# 4 0 NA 0
# 5 0 0 NA
# 6 0 0 NA
Why do this? From OP's statement, I can know that list1
can be ragged, while list2
can not (because later OP wants to turn the updated list2
into a data frame). Therefore, there is a way to use fast indexing to solve this problem.
Thanks to @alexis_laz's comment, that I could use
y <- unlist(list2, use.names = FALSE)
instead of
y <- unname(unlist(list2))
Upvotes: 4
Reputation: 38510
Here's a method that uses Map
:
myDf <- data.frame(Map(function(x, y) {y[x] <- NA; y}, list1, list2))
names(myDf) <- paste0("X", 1:ncol(myDf))
which returns
myDf
X1 X2 X3
1 NA 0 0
2 NA 0 0
3 0 NA 0
4 0 NA 0
5 0 0 NA
6 0 0 NA
Map produces a list object, which is wrapped in data.frame
to return the proper object. However, it is necessary to provide a nicer name to each column with names
.
Upvotes: 2
Reputation: 6979
Just use for:
list1 <- list(1:2, 3:4, 5:6)
df <- data.frame(mat.or.vec(6, 3))
for(i in 1:length(list1)) {
df[list1[[i]], i] <- NA
}
# df
# X1 X2 X3
# 1 NA 0 0
# 2 NA 0 0
# 3 0 NA 0
# 4 0 NA 0
# 5 0 0 NA
# 6 0 0 NA
Upvotes: 3