【问题标题】:STEM: Create sequential combinations of each row in RSTEM:在 R 中创建每一行的顺序组合
【发布时间】:2017-06-04 22:43:28
【问题描述】:

想在 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 第一行的第一块:

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 http://stackoverflow.com/questions/17308551/do-callrbind-list-for-uneven-number-of-column
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)。它采用一个包含节点深度不同的树的表,仅列出结束节点,并将其转换为包含树的所有顺序组合的表。

【问题讨论】:

  • NAs 来自哪里? expand.grid 不插入 NAs。
  • NA 只是占位符
  • 为什么Animal列中没有NAs?
  • 为什么没有Cat NA 10 行?
  • @Gregor 因为顺序性(从左到右)。

标签: r matrix dplyr apply


【解决方案1】:

一个 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

【讨论】:

  • 本着这个问题的精神,鉴于您的答案是使用 dplyr,我会给您打勾以使其适应不同的列环境。就目前而言,用户似乎需要包含一堆额外的 group_by 语句,每个列都有特定的名称。
【解决方案2】:

应该有比这更有效的答案,这只是一个尝试!

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

【讨论】:

  • 嵌套applys的大用处
【解决方案3】:

事实证明,一个 for 循环可以用一个列表解决这个问题,这比我最初想象的要容易得多,并且它可以推广到具有不同节点深度的 nrows。这与 joel 对两行示例的出色回答的速度相同。但是,目前可以并行化,以便在使用 Matrix 之外更快地读取。注意:如果节点深度不同,Joel 和我自己的答案都需要unique - 例如,NA 代替 dat 表中的 20 值。

library(dplyr)
datInner <- list()
for(i in 1:ncol(dat)){ datInner[[i]] <- dat[1:i] }; # foreach %dopar% for parallel
datInner %>% bind_rows  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 2016-01-04
    相关资源
    最近更新 更多