STEM:在 R 中创建每一行的顺序组合
STEM: Create sequential combinations of each row in R
想在 R 中创建一个新的数据框,它采用一组行,并以 nrow
* nrow
* ncol
格式组合每个变体。
library(dplyr)
dat <- read.table(text =
" Animal Color Size
Cat Orange 10
Dog Black 20", header=TRUE)
想要这样的输出:
Animal Color Size
Cat NA NA
Cat Orange NA
Cat Orange 10
Dog NA NA
Dog Black NA
Dog Black 20
R 中是否有可以执行此操作的函数 -- 类似于 expand.grid
?
expand.grid(dat$Animal, dat$Color, dat$Size) %>% arrange(Var1, Var2, Var3) #Note: this does not give the correct answer.
我可以使用以下方法创建数据第一行的第一块:
dat <- c("Cat", "Orange", 10)
counter <- 1
datInner <- list()
for(i in 1:length(dat)){ # loops through 3x
# i <- 3
datInner[[i]] <- dat[1:i]
counter <- counter + 1
}
library(plyr)
# Adapted from
plyr::rbind.fill(lapply(datInner, function(y){as.data.frame(t(y),
stringsAsFactors = FALSE)}))
# V1 V2 V3
# 1 Cat <NA> <NA>
# 2 Cat Orange <NA>
# 3 Cat Orange 10
注意:将此函数类型称为顺序树扩展矩阵 (STEM)。它需要一个 table 和一棵节点深度不同的树,仅列出端节点,并将其转换为 table 和树的所有顺序组合。
dplyr 解决方案 - 不是很通用。
library(dplyr)
rbind(
dat %>%
group_by(Animal) %>%
summarize(Color = NA, Size = NA) %>%
ungroup(),
dat %>%
group_by(Animal, Color) %>%
summarize(Size = NA) %>%
ungroup(),
dat) %>% arrange(Animal)
# Animal Color Size
#1 Cat <NA> NA
#2 Cat Orange NA
#3 Cat Orange 10
#4 Dog <NA> NA
#5 Dog Black NA
#6 Dog Black 20
应该有比这更有效的答案,这只是一个尝试!
m <- t(sapply(1:ncol(dat), function(i) c(1:i, rep(NA, (ncol(dat)-i)))))
m
# [,1] [,2] [,3]
#[1,] 1 NA NA
#[2,] 1 2 NA
#[3,] 1 2 3
#2. now i apply each row to original data (dat) Basically performing subset
m1 <- apply(dat, 1, function(i) apply(m, 1, function(j) i[j]))
data.frame(matrix(m1, byrow = T, ncol = ncol(dat)))
# X1 X2 X3
#1 Cat <NA> <NA>
#2 Cat Orange <NA>
#3 Cat Orange 10
#4 Dog <NA> <NA>
#5 Dog Black <NA>
#6 Dog Black 20
注意:最后一列是 factor
因为它在 matrix
中
事实证明,for 循环可以用列表解决这个问题比我最初想象的要容易得多,而且它可以推广到具有不同节点深度的 nrows。这与乔尔对两行示例的出色回答的速度相同。但是,目前可以将其并行化,以便在使用 Matrix 之外更快地读取。注意:如果节点深度不同,Joel 和我自己的回答都需要 unique
——例如,NA 代替 dat table.
中的 20 值
library(dplyr)
datInner <- list()
for(i in 1:ncol(dat)){ datInner[[i]] <- dat[1:i] }; # foreach %dopar% for parallel
datInner %>% bind_rows
想在 R 中创建一个新的数据框,它采用一组行,并以 nrow
* nrow
* ncol
格式组合每个变体。
library(dplyr)
dat <- read.table(text =
" Animal Color Size
Cat Orange 10
Dog Black 20", header=TRUE)
想要这样的输出:
Animal Color Size
Cat NA NA
Cat Orange NA
Cat Orange 10
Dog NA NA
Dog Black NA
Dog Black 20
R 中是否有可以执行此操作的函数 -- 类似于 expand.grid
?
expand.grid(dat$Animal, dat$Color, dat$Size) %>% arrange(Var1, Var2, Var3) #Note: this does not give the correct answer.
我可以使用以下方法创建数据第一行的第一块:
dat <- c("Cat", "Orange", 10)
counter <- 1
datInner <- list()
for(i in 1:length(dat)){ # loops through 3x
# i <- 3
datInner[[i]] <- dat[1:i]
counter <- counter + 1
}
library(plyr)
# Adapted from
plyr::rbind.fill(lapply(datInner, function(y){as.data.frame(t(y),
stringsAsFactors = FALSE)}))
# V1 V2 V3
# 1 Cat <NA> <NA>
# 2 Cat Orange <NA>
# 3 Cat Orange 10
注意:将此函数类型称为顺序树扩展矩阵 (STEM)。它需要一个 table 和一棵节点深度不同的树,仅列出端节点,并将其转换为 table 和树的所有顺序组合。
dplyr 解决方案 - 不是很通用。
library(dplyr)
rbind(
dat %>%
group_by(Animal) %>%
summarize(Color = NA, Size = NA) %>%
ungroup(),
dat %>%
group_by(Animal, Color) %>%
summarize(Size = NA) %>%
ungroup(),
dat) %>% arrange(Animal)
# Animal Color Size
#1 Cat <NA> NA
#2 Cat Orange NA
#3 Cat Orange 10
#4 Dog <NA> NA
#5 Dog Black NA
#6 Dog Black 20
应该有比这更有效的答案,这只是一个尝试!
m <- t(sapply(1:ncol(dat), function(i) c(1:i, rep(NA, (ncol(dat)-i)))))
m
# [,1] [,2] [,3]
#[1,] 1 NA NA
#[2,] 1 2 NA
#[3,] 1 2 3
#2. now i apply each row to original data (dat) Basically performing subset
m1 <- apply(dat, 1, function(i) apply(m, 1, function(j) i[j]))
data.frame(matrix(m1, byrow = T, ncol = ncol(dat)))
# X1 X2 X3
#1 Cat <NA> <NA>
#2 Cat Orange <NA>
#3 Cat Orange 10
#4 Dog <NA> <NA>
#5 Dog Black <NA>
#6 Dog Black 20
注意:最后一列是 factor
因为它在 matrix
事实证明,for 循环可以用列表解决这个问题比我最初想象的要容易得多,而且它可以推广到具有不同节点深度的 nrows。这与乔尔对两行示例的出色回答的速度相同。但是,目前可以将其并行化,以便在使用 Matrix 之外更快地读取。注意:如果节点深度不同,Joel 和我自己的回答都需要 unique
——例如,NA 代替 dat table.
library(dplyr)
datInner <- list()
for(i in 1:ncol(dat)){ datInner[[i]] <- dat[1:i] }; # foreach %dopar% for parallel
datInner %>% bind_rows