R - 将列表元素变成 header

R - Make list element into a header

碰巧 给出的列表中有两个元素不符合模式。这意味着,在将@akrun 的代码应用于该列表后,我遇到了以下问题:

lst <- list(A = c('aa','bb','B', 'cc', 'dd', 'C', 'ee', 'ff'), D = (c('aa', 'bb')))

$A
 [1] "aa" "bb" "B" "cc" "dd" "C"  "ee" "ff"

$D
[1] "aa" "bb"

在不影响整体列表结构的情况下,我如何制作 "B" 和 "C" headers 各自的元素,以便:

lst2 <- list(A=c('aa', 'bb'), B=c('cc', 'dd'), C=c('ee', 'ff'), D=c('aa', 'bb'))

$A
[1] "aa" "bb"

$B
[1] "cc" "dd"

$C
[1] "ee" "ff"

$D
[1] "aa" "bb"

我设法解决了这样的实际问题:

> lst <- list('隱公元年', c("", 'aa'), 'bb', 'cc', '莊公十年', 'aa', 'bb', '襄公二十四年', c("", 'dd'), '成公三年', 'ee')

> v1 <- unlist(lst)
> v2 <- lapply(v1, function(x){x[!x ==""]}) %>% compact %>% unlist() #Remove empty string

> i1 <- cumsum(grepl(".公+[元一二三四五六七八九十]+年$", v2)) #Generate index based on Regex of intended headers. 

> zz <- tapply(v2, i1, FUN = function(x) x[-1]) #Apply index to dataset, ignoring first element (which is the header). 
> names(zz) <- tapply(v2, i1, FUN = head, 1) #Apply headers to dataset. 

> zz
$隱公元年
[1] "aa" "bb" "cc"

$莊公十年
[1] "aa" "bb"

$襄公二十四年
[1] "dd"

$成公三年
[1] "ee"

这是一个选项,我们 stacklist 转换为 2 列 'data.frame' ('d1')。将其转换为 data.table (setDT(d1)),指定具有逻辑条件的 i,即检查 'values' 中的大写元素并将这些值分配给 (:=) 'ind' 该位置的列。基于 'ind' 中 unique 元素的位置创建的分组变量与行序列比较,得到累积和,以此将 'ind' 分配为 [= 的第一个元素33=] (ind[1]),保留 'values' 不等于 'ind' 和 split 'values' 的行到 'ind' 列

d1 <- stack(lst)
library(data.table)
d2 <- setDT(d1)[grepl("[A-Z]", values), ind := values][, 
  ind := ind[1L] , cumsum(seq_len(nrow(d1)) %in% match(unique(ind), ind))][values != ind]
split(d2$values, d2$ind)
#$A
#[1] "aa" "bb" "cc"

#$D
#[1] "aa" "bb"

#$B
#[1] "aa" "bb" "cc" "dd"

#$C
#[1] "ee" "ff"

或者我们可以尝试 tidyverse

library(purrr)
library(dplyr)
fsplitLst <- function(lstt){

f1 <- function(x) {
     i1 <- grepl("[A-Z]", x)
     grp <- cumsum(i1)
     split(x[!i1], grp[!i1])
     
   }
 map(lstt, f1) %>%
        flatten %>%
        set_names(., map2(names(lstt), lstt, ~grep("[A-Z]", c(.x, .y), value = TRUE)) %>%
           unlist)
 }
fsplitLst(lst)
#$A
#[1] "aa" "bb" "cc"

#$B
#[1] "aa" "bb" "cc" "dd"

#$C
#[1] "ee" "ff"

#$D
#[1] "aa" "bb"

数据

lst <- list(A = c('aa','bb','cc', 'B', 'aa','bb', 'cc', 'dd', 'C', 'ee', 'ff'),
             D = c('aa', 'bb'))