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"
这是一个选项,我们 stack
将 list
转换为 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'))
碰巧
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"
这是一个选项,我们 stack
将 list
转换为 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'))