R - 在lapply中的unlist中的递归行为

时间:2017-09-12 20:34:29

标签: r list lapply

我正在开发一个自定义函数,我需要将其应用于一组文本。我有一个函数读入的文档名称向量,抓取一段元数据和一些关键字,并生成列表列表,其中外部列表​​是文档列表,内部列表各自包含[[1] ]元数据(数字向量)和[[2]]关键字(字符元素矩阵)。我需要将其转换为包含元数据和关键字的单个unnested列表,即,如果我有12个文档,则此列表将包含24个元素。

我在这里提供的示例比我实际处理的更简单很多,但它再现了我遇到的问题。我之所以提到这一点,只是因为玩具版本的一些看似明显的解决方案可能不会对真实数据起作用,特别是如果它们依赖于改变输入格式。

doc1 <- c("aa","bb","cccc")
doc2 <- c("abc","dd","eee","ff")
doc3 <- c("bd","qh")

docs <- c(doc1,doc2,doc3)

get_outputs <- function(x) {
current_doc <- as.vector(x)
doc_length <- 1 ##this is dynamic in the real code but not the problem here
input_list <- list(doc_length,current_doc)
unlisted_outputs <- unlist(input_list,recursive=FALSE)
##some more code would go here that operates on unlisted_outputs 
##but this is where the problem occurs
return(unlisted_outputs)
}

lapply(docs,get_outputs)
[[1]]
[1] "1"  "aa"

[[2]]
[1] "1"  "bb"

[[3]]
[1] "1"    "cccc"

[[4]]
[1] "1"   "abc"

[[5]]
[1] "1"  "dd"

...等

但我真正想要的输出是我得到的:

get_outputs2 <- function(x) {
current_doc <- as.vector(x)
doc_length <- 1
input_list <- list(doc_length,current_doc)
return(input_list)
}

unlist(lapply(docs,get_outputs2),recursive=FALSE)

[[1]]
[1] 1

[[2]]
[1] "aa"

[[3]]
[1] 1

[[4]]
[1] "bb"

...等

我喜欢这种输出格式是有原因的,尽管如果我能得到类似的东西:

[[1]]
[1] 1
[2] 1
[3] 1
...

[[2]]
[1] "aa"
[2] "bb"
[3] "cccc"
...

也没关系。

我提出的关于输出列表列表和在函数外部不列出的解决方案不是我的偏好,因为我希望函数在返回之前做下游的其他事情,但是我不能轻易地做那些事情在列表清单上。欣赏任何人可能有的想法。

更新:我想再次强调,导致数据结构看起来像input_list的步骤之前的所有内容都无法更改。我意识到,如果可以更干净地读取数据,就像在这个玩具示例中那样可以更容易地读取问题,但是在实际数据中它可以,或者至少为了这个问题的目的,我们应该假设它不能。我特意寻找一种获取unlist(x,recursive = TRUE)的方法,或者非常喜欢它的方式,以lapply的方式在lapply之外的方式运行。

3 个答案:

答案 0 :(得分:1)

如果不了解真实数据的结构,很难提供一般解决方案。不过,你是说这些输出是不可取的吗?

list(rep(seq_along(docs), lengths(docs)), unlist(docs))

# [[1]]
# [1] 1 1 1 2 2 2 2 3 3

# [[2]]
# [1] "aa"   "bb"   "cccc" "abc"  "dd"   "eee"  "ff"   "bd"   "qh"

cbind(rep(seq_along(docs), lengths(docs)), unlist(docs))

     # [,1] [,2]  
 # [1,] "1"  "aa"  
 # [2,] "1"  "bb"  
 # [3,] "1"  "cccc"
 # [4,] "2"  "abc" 
 # [5,] "2"  "dd"  
 # [6,] "2"  "eee" 
 # [7,] "2"  "ff"  
 # [8,] "3"  "bd"  
 # [9,] "3"  "qh"

答案 1 :(得分:0)

从问题描述中我假设一个具有以下结构的列表:

l = list(list("doc1",list("meta1","key1")),list("doc2",list("meta2","key2")))

>l

#[[1]]
#[[1]][[1]]
#[1] "doc1"

#[[1]][[2]]
#[[1]][[2]][[1]]
#[1] "meta1"

#[[1]][[2]][[2]]
#[1] "key1"



#[[2]]
#[[2]][[1]]
#[1] "doc2"

#[[2]][[2]]
#[[2]][[2]][[1]]
#[1] "meta2"

#[[2]][[2]][[2]]
#[1] "key2"

以下代码可以帮助您摆脱嵌套结构:

meta = sapply(
            sapply(
               lapply(l,"[[",2),
            function(t){unlist(t)},simplify = T),
       list,USE.NAMES = F)

>meta
#[[1]]
#[1] "meta1"

#[[2]]
#[1] "key1"

#[[3]]
#[1] "meta2"

#[[4]]
#[1] "key2"

答案 2 :(得分:0)

我非常感谢你的努力@CPak @Frank @tushaR,但他们并没有让我得到我想要的东西。我用嵌套函数解决了我的问题:

get_unlisted_outputs <- function(y){

   get_outputs2 <- function(x) {
     current_doc <- as.vector(x)
     doc_length <- 1
     input_list <- list(doc_length,current_doc)
     return(input_list)
   }

  intermediate_step <- lapply(y,get_outputs2)
  unlisted_outputs <- unlist(intermediate_step,recursive=FALSE)
  return(unlisted_outputs)
  }

get_unlisted_outputs(docs)