【问题标题】:R - Collapse into vector same member of a listR - 折叠成向量列表的相同成员
【发布时间】:2016-10-19 20:22:24
【问题描述】:

我的每个成员都有一个与以下结构相同的列表

config <- NULL

config[["secA"]] <- NULL
config[["secA"]]$VAL <- 0
config[["secA"]]$ARR <- c(1,2,3,4,5)
config[["secA"]]$DF  <- data.frame(matrix(c(1,5,3,8),2,2))

config[["secB"]] <- NULL
config[["secB"]]$VAL <- 1
config[["secB"]]$ARR <- c(1,3,2,4,9)
config[["secB"]]$DF  <- data.frame(matrix(c(2,6,1,9),2,2))

config[["secC"]] <- NULL
config[["secC"]]$VAL <- 5
config[["secC"]]$ARR <- c(4,2,1,5,8)
config[["secC"]]$DF  <- data.frame(matrix(c(4,2,1,7),2,2))

我需要获得 3 个向量 VALARRDF,每个向量都有对应成员的串联元素。比如

# VAL: 0,1,5
# ARR: 1,2,3,4,5,1,3,2,4,9,4,2,1,5,8
# DF:  1,5,3,8,2,6,1,9,4,2,1,7

看到类似的情况,我觉得我需要使用do.callcbindlapply 的组合,但我不知道。有什么建议吗?

【问题讨论】:

  • 我需要用作.C函数的输入

标签: r list vector collapse


【解决方案1】:
config <- NULL

config[["secA"]] <- NULL
config[["secA"]]$VAL <- 0
config[["secA"]]$ARR <- c(1,2,3,4,5)
config[["secA"]]$DF  <- data.frame(matrix(c(1,5,3,8),2,2))

config[["secB"]] <- NULL
config[["secB"]]$VAL <- 1
config[["secB"]]$ARR <- c(1,3,2,4,9)
config[["secB"]]$DF  <- data.frame(matrix(c(2,6,1,9),2,2))

config[["secC"]] <- NULL
config[["secC"]]$VAL <- 5
config[["secC"]]$ARR <- c(4,2,1,5,8)
config[["secC"]]$DF  <- data.frame(matrix(c(4,2,1,7),2,2))

sapply(names(config[[1]]), function(x)
  unname(unlist(sapply(config, `[`, x))), USE.NAMES = TRUE)

# $VAL
# [1] 0 1 5
# 
# $ARR
# [1] 1 2 3 4 5 1 3 2 4 9 4 2 1 5 8
# 
# $DF
# [1] 1 5 3 8 2 6 1 9 4 2 1 7

或者你可以使用this clist函数

很遗憾,没有其他答案。

(l <- Reduce(clist, config))
# $VAL
# [1] 0 1 5
# 
# $ARR
# [1] 1 2 3 4 5 1 3 2 4 9 4 2 1 5 8
# 
# $DF
#   X1 X2 X1 X2 X1 X2
# 1  1  3  2  1  4  1
# 2  5  8  6  9  2  7

它合并了数据框和矩阵,所以你需要unlist才能得到你想要的向量

l$DF <- unname(unlist(l$DF))
l
# $VAL
# [1] 0 1 5
# 
# $ARR
# [1] 1 2 3 4 5 1 3 2 4 9 4 2 1 5 8
# 
# $DF
# [1] 1 5 3 8 2 6 1 9 4 2 1 7

功能

clist <- function (x, y) {
  islist <- function(x) inherits(x, 'list')
  '%||%' <- function(a, b) if (!is.null(a)) a else b
  get_fun <- function(x, y)
    switch(class(x %||% y),
           matrix = cbind,
           data.frame = function(x, y)
             do.call('cbind.data.frame', Filter(Negate(is.null), list(x, y))),
           factor = function(...) unlist(list(...)), c)

  stopifnot(islist(x), islist(y))
  nn <- names(rapply(c(x, y), names, how = 'list'))
  if (is.null(nn) || any(!nzchar(nn)))
    stop('All non-NULL list elements should have unique names', domain = NA)

  nn <- unique(c(names(x), names(y)))
  z <- setNames(vector('list', length(nn)), nn)

  for (ii in nn)
    z[[ii]] <- if (islist(x[[ii]]) && islist(y[[ii]]))
      Recall(x[[ii]], y[[ii]]) else
        (get_fun(x[[ii]], y[[ii]]))(x[[ii]], y[[ii]])
  z
}

【讨论】:

  • 好的。绝对超出我的范围...非常感谢!没有这个,我可以在这里待很久!
  • @Stefano 我的意思是我确定还有其他方法,但我会这样做,因为我花时间编写并测试它,而且我知道它已经存在
  • @Stefano 我添加了一个单行,如果您只需要返回向量,它应该可以很好地工作
  • 是的,我们的想法是将向量作为 .C 函数只允许数组作为输入。明天,我将在我自己的代码中尝试一下。再次感谢!
【解决方案2】:

另一种方法,代码略少。

un_config <- unlist(config)

un_configNAM <- names(un_config)

vecNAM <- c("VAL", "ARR", "DF")

for(n in vecNAM){
  assign(n, un_config[grepl(n, un_configNAM)])
}

这将按照 OP 的要求返回 3 个向量。但是,通常将结果存储在 rawr 建议的列表中更有利。您当然可以采用上述代码,将结果存储在列表中。

l <- rep(list(NA), length(vecNAM))

i = 1
for(n in vecNAM){
  l[[i]] <- un_config[grepl(n, un_configNAM)]
  i = i +1
}

【讨论】:

  • 嗯...我只是仔细检查了一下,对我来说效果很好。也许先清理你的工作空间?
  • 只是我没有看到您的答案的编辑。我现在明白了 :) 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
  • 2021-05-29
  • 2016-01-02
  • 2017-11-10
  • 1970-01-01
  • 2019-10-12
相关资源
最近更新 更多