expand.grid 每列都有单独的变量
expand.grid with separate variable for each column
我想在 R 中实现以下 data.frame
:
i1 i2 i3
1 A1 A2 A3
2 No A2 A3
3 A1 No A3
4 No No A3
5 A1 A2 No
6 No A2 No
7 A1 No No
8 No No No
在每一列中,变量可以是连接的字符串 "A" 和列号或 "No". data.frame
应该包含所有可能的组合。
我的想法是使用 expand.grid
,但我不知道如何动态创建 list
。或者有更好的方法吗?
expand.grid(list(c("A1", "No"), c("A2", "No"), c("A3", "No")))
我猜你可以创建自己的辅助函数,类似的东西
MyList <- function(n) expand.grid(lapply(paste0("A", seq_len(n)), c, "No"))
然后简单地传递元素的数量(例如,3)
MyList(3)
# Var1 Var2 Var3
# 1 A1 A2 A3
# 2 No A2 A3
# 3 A1 No A3
# 4 No No A3
# 5 A1 A2 No
# 6 No A2 No
# 7 A1 No No
# 8 No No No
或者,您也可以尝试 data.table
s CJ
等价物,对于大的 n
,它应该比 expand.grid
更有效
library(data.table)
DTCJ <- function(n) do.call(CJ, lapply(paste0("A", seq_len(n)), c, "No"))
DTCJ(3) # will return a sorted cross join
# V1 V2 V3
# 1: A1 A2 A3
# 2: A1 A2 No
# 3: A1 No A3
# 4: A1 No No
# 5: No A2 A3
# 6: No A2 No
# 7: No No A3
# 8: No No No
另一种选择是使用 Map
和 expand.grid
n <- 3
expand.grid(Map(c, paste0('A', seq_len(n)), 'NO'))
或者
expand.grid(as.data.frame(rbind(paste0('A', seq_len(n)),'NO')))
另一种选择,仅使用 R 中最基本的函数,是使用索引:
df <- data.frame(V1 = c('A','A','A', 'A',rep('No',4)), V2 = c('A','A','No','No','A','A','No','No'), V3 = c('A','No','A','No','A','No','A','No'), stringsAsFactors = FALSE)
获取我们需要更改的元素的行索引和列索引:
rindex <- which(df != 'No') %% nrow(df)
cindex <- ceiling(which(df != 'No')/nrow(df))
解决方案基本上是一条线:
df[matrix(c(rindex,cindex),ncol=2)] <- paste0(df[matrix(c(rindex,cindex),ncol=2)],cindex)
> df
V1 V2 V3
1 A1 A2 A3
2 A1 A2 No
3 A1 No A3
4 A1 No No
5 No A2 A3
6 No A2 No
7 No No A3
8 No No No
我想在 R 中实现以下 data.frame
:
i1 i2 i3
1 A1 A2 A3
2 No A2 A3
3 A1 No A3
4 No No A3
5 A1 A2 No
6 No A2 No
7 A1 No No
8 No No No
在每一列中,变量可以是连接的字符串 "A" 和列号或 "No". data.frame
应该包含所有可能的组合。
我的想法是使用 expand.grid
,但我不知道如何动态创建 list
。或者有更好的方法吗?
expand.grid(list(c("A1", "No"), c("A2", "No"), c("A3", "No")))
我猜你可以创建自己的辅助函数,类似的东西
MyList <- function(n) expand.grid(lapply(paste0("A", seq_len(n)), c, "No"))
然后简单地传递元素的数量(例如,3)
MyList(3)
# Var1 Var2 Var3
# 1 A1 A2 A3
# 2 No A2 A3
# 3 A1 No A3
# 4 No No A3
# 5 A1 A2 No
# 6 No A2 No
# 7 A1 No No
# 8 No No No
或者,您也可以尝试 data.table
s CJ
等价物,对于大的 n
expand.grid
更有效
library(data.table)
DTCJ <- function(n) do.call(CJ, lapply(paste0("A", seq_len(n)), c, "No"))
DTCJ(3) # will return a sorted cross join
# V1 V2 V3
# 1: A1 A2 A3
# 2: A1 A2 No
# 3: A1 No A3
# 4: A1 No No
# 5: No A2 A3
# 6: No A2 No
# 7: No No A3
# 8: No No No
另一种选择是使用 Map
和 expand.grid
n <- 3
expand.grid(Map(c, paste0('A', seq_len(n)), 'NO'))
或者
expand.grid(as.data.frame(rbind(paste0('A', seq_len(n)),'NO')))
另一种选择,仅使用 R 中最基本的函数,是使用索引:
df <- data.frame(V1 = c('A','A','A', 'A',rep('No',4)), V2 = c('A','A','No','No','A','A','No','No'), V3 = c('A','No','A','No','A','No','A','No'), stringsAsFactors = FALSE)
获取我们需要更改的元素的行索引和列索引:
rindex <- which(df != 'No') %% nrow(df)
cindex <- ceiling(which(df != 'No')/nrow(df))
解决方案基本上是一条线:
df[matrix(c(rindex,cindex),ncol=2)] <- paste0(df[matrix(c(rindex,cindex),ncol=2)],cindex)
> df
V1 V2 V3
1 A1 A2 A3
2 A1 A2 No
3 A1 No A3
4 A1 No No
5 No A2 A3
6 No A2 No
7 No No A3
8 No No No