使用 assign 在 for 循环中创建对象
Using assign to create objects in a for loop
我有如下示例数据:
# Two lists of vectors
A <- list()
B <- list()
patterns <- c("A","B")
A[[1]] <- c("Aa", "Aa", "Ab", NA)
names(A)[1] <- "A1"
A[[2]] <- c("Aa", "Aa", "Ab", NA, NA)
names(A)[2] <- "A2"
B[[1]] <- c("Aa", "Ab", NA, NA, "Ab")
names(B)[1] <- "B1"
B[[2]] <- c("Aa", "Ab", NA, "Ab")
names(B)[2] <- "B2"
我想做的是从每个列表项创建 data.frames,每个列表项只有唯一值。
for (j in 1:length(patterns)) {
# Keep unique values
assign(paste0("Pattern_", patterns[[j]]), lapply(paste0("Pattern_", patterns[[j]]) ,function(x) unique(na.omit(x))))
# Make lengths equal
assign(paste0("Pattern_", patterns[[j]]), lapply(paste0("Pattern_", patterns[[j]]), `length<-`, max(lengths(paste0("Pattern_", patterns[[j]])))))
# Create data.frame
assign(paste0("Pattern_", patterns[[j]]), data.frame(matrix(unlist(paste0("Pattern_", patterns[[j]])), nrow=length(paste0("Pattern_", patterns[[j]])), byrow=TRUE),stringsAsFactors=FALSE))
}
我以为我做对了,但不知何故我得到的是:
我想要的是:
A <- lapply(A ,function(x) unique(na.omit(x)))
A <- lapply(A, `length<-`, max(lengths(A)))
#
A <- data.frame(ID = rep(names(A), sapply(A, length)),
Match = unlist(A), row.names = NULL)
ID Match
1 A1 Aa
2 A1 Ab
3 A2 Aa
4 A2 Ab
我做错了什么?
我会做一个更简单的方法:
library(tidyverse)
# Two lists of vectors
A <- list()
B <- list()
patterns <- c("A","B")
A[[1]] <- c("Aa", "Aa", "Ab", NA)
names(A)[1] <- "A1"
A[[2]] <- c("Aa", "Aa", "Ab", NA, NA)
names(A)[2] <- "A2"
B[[1]] <- c("Aa", "Ab", NA, NA, "Ab")
names(B)[1] <- "B1"
B[[2]] <- c("Aa", "Ab", NA, "Ab")
names(B)[2] <- "B2"
stack(A) %>% distinct(ind, values)
#> values ind
#> 1 Aa A1
#> 2 Ab A1
#> 3 <NA> A1
#> 4 Aa A2
#> 5 Ab A2
#> 6 <NA> A2
然后您可以过滤掉 NA
s。
由 reprex package (v2.0.0)
于 2021-11-05 创建
编辑
我建议永远不要使用 assign
,因为您在代码中引入了副作用。
代码的问题在于您从不调用列表,而是在 lapply()
函数中使用字符串:
lapply(paste0("Pattern_", patterns[[j]]) ,function(x) unique(na.omit(x)))
我保留了 assign
,尽管我不喜欢它。
for (j in patterns) {
new_list <- lapply(get(j) ,function(x) unique(na.omit(x)))
assign(paste0("Pattern_", j), stack(new_list))
}
我有如下示例数据:
# Two lists of vectors
A <- list()
B <- list()
patterns <- c("A","B")
A[[1]] <- c("Aa", "Aa", "Ab", NA)
names(A)[1] <- "A1"
A[[2]] <- c("Aa", "Aa", "Ab", NA, NA)
names(A)[2] <- "A2"
B[[1]] <- c("Aa", "Ab", NA, NA, "Ab")
names(B)[1] <- "B1"
B[[2]] <- c("Aa", "Ab", NA, "Ab")
names(B)[2] <- "B2"
我想做的是从每个列表项创建 data.frames,每个列表项只有唯一值。
for (j in 1:length(patterns)) {
# Keep unique values
assign(paste0("Pattern_", patterns[[j]]), lapply(paste0("Pattern_", patterns[[j]]) ,function(x) unique(na.omit(x))))
# Make lengths equal
assign(paste0("Pattern_", patterns[[j]]), lapply(paste0("Pattern_", patterns[[j]]), `length<-`, max(lengths(paste0("Pattern_", patterns[[j]])))))
# Create data.frame
assign(paste0("Pattern_", patterns[[j]]), data.frame(matrix(unlist(paste0("Pattern_", patterns[[j]])), nrow=length(paste0("Pattern_", patterns[[j]])), byrow=TRUE),stringsAsFactors=FALSE))
}
我以为我做对了,但不知何故我得到的是:
我想要的是:
A <- lapply(A ,function(x) unique(na.omit(x)))
A <- lapply(A, `length<-`, max(lengths(A)))
#
A <- data.frame(ID = rep(names(A), sapply(A, length)),
Match = unlist(A), row.names = NULL)
ID Match
1 A1 Aa
2 A1 Ab
3 A2 Aa
4 A2 Ab
我做错了什么?
我会做一个更简单的方法:
library(tidyverse)
# Two lists of vectors
A <- list()
B <- list()
patterns <- c("A","B")
A[[1]] <- c("Aa", "Aa", "Ab", NA)
names(A)[1] <- "A1"
A[[2]] <- c("Aa", "Aa", "Ab", NA, NA)
names(A)[2] <- "A2"
B[[1]] <- c("Aa", "Ab", NA, NA, "Ab")
names(B)[1] <- "B1"
B[[2]] <- c("Aa", "Ab", NA, "Ab")
names(B)[2] <- "B2"
stack(A) %>% distinct(ind, values)
#> values ind
#> 1 Aa A1
#> 2 Ab A1
#> 3 <NA> A1
#> 4 Aa A2
#> 5 Ab A2
#> 6 <NA> A2
然后您可以过滤掉 NA
s。
由 reprex package (v2.0.0)
于 2021-11-05 创建编辑
我建议永远不要使用 assign
,因为您在代码中引入了副作用。
代码的问题在于您从不调用列表,而是在 lapply()
函数中使用字符串:
lapply(paste0("Pattern_", patterns[[j]]) ,function(x) unique(na.omit(x)))
我保留了 assign
,尽管我不喜欢它。
for (j in patterns) {
new_list <- lapply(get(j) ,function(x) unique(na.omit(x)))
assign(paste0("Pattern_", j), stack(new_list))
}