R - 改变列表结构
R - alter list structure
我有一些文本数据在读入 R 后以下列格式呈现:
> lst <- list('A', c("", 'aa'), 'bb', 'cc', 'B', c("", 'aa'), 'bb', 'cc', 'dd')
[[1]]
[1] "A"
[[2]]
[1] "" "aa"
[[3]]
[1] "bb"
[[4]]
[1] "cc"
[[5]]
[1] "B"
[[6]]
[1] "" "aa"
[[7]]
[1] "bb"
[[8]]
[1] "cc"
[[9]]
[1] "dd"
有没有一种简单的方法可以更改此列表的结构,使用“”作为指示符,使紧接在“”之前的项目成为列表标题?
lst2 <- list(A=c('aa', 'bb', 'cc'), B=c('aa', 'bb', 'cc', 'dd'))
$A
[1] "aa" "bb" "cc"
$B
[1] "aa" "bb" "cc" "dd"
我们可以unlist
将list
转换为vector
('v1'),然后根据空字符串的位置创建分组索引(!nzchar(v1)
), 删除第一个元素并在末尾附加 FALSE ,得到累积和,以便该组从出现空字符串之前的位置开始。然后,我们在 tapply
中使用它,删除向量的第一个元素并使用 group by 操作获取向量的第一个元素,用于命名 'lst2'
v1 <- unlist(lst)
i1 <- cumsum(c(!nzchar(v1)[-1], FALSE))
lst2 <- tapply(v1, i1, FUN = function(x) x[-(1:2)])
names(lst2) <- tapply(v1, i1, FUN = head, 1)
lst2
#$A
#[1] "aa" "bb" "cc"
#$B
#[1] "aa" "bb" "cc" "dd"
另一个可能的选择:
spl_vals <- c("")
idxs <- lapply(lst, function(x) as.numeric(any(spl_vals %in% x))) #Find location of split values
c_idxs <- cumsum(idxs) #Use cumsum to group sets of values
c_idxs[which(idxs==1) - 1] <- 0 #Assign the value before each split to be 0. This will be the name of the element
spl <- split(lst, c_idxs) #Split you list into (1) names of elements and (2) individual elements
newlist <- lapply(spl, function(x) unlist(x)[!unlist(x) %in% spl_vals]) #Remove any split values
nms <- names(newlist) #Extract names of list (this is just for shortening the next line of code)
setNames(newlist[nms[!nms %in% "0"]], newlist[["0"]]) #Set names of elements
$A
[1] "aa" "bb" "cc"
$B
[1] "aa" "bb" "cc" "dd"
请注意,这不会从一开始就使用 unlist
,因此如果您有多个拆分值并且您希望两个元素具有不同的类型(例如字符和整数),这会保留该类型。例如,使用:
lst <- list('A', c("", 'aa'), 'bb', 'cc', 'B', c(0, 1), 2, 3, 4)
spl_vals <- c("",0)
你得到:
$A
[1] "aa" "bb" "cc"
$B
[1] 1 2 3 4
我有一些文本数据在读入 R 后以下列格式呈现:
> lst <- list('A', c("", 'aa'), 'bb', 'cc', 'B', c("", 'aa'), 'bb', 'cc', 'dd')
[[1]]
[1] "A"
[[2]]
[1] "" "aa"
[[3]]
[1] "bb"
[[4]]
[1] "cc"
[[5]]
[1] "B"
[[6]]
[1] "" "aa"
[[7]]
[1] "bb"
[[8]]
[1] "cc"
[[9]]
[1] "dd"
有没有一种简单的方法可以更改此列表的结构,使用“”作为指示符,使紧接在“”之前的项目成为列表标题?
lst2 <- list(A=c('aa', 'bb', 'cc'), B=c('aa', 'bb', 'cc', 'dd'))
$A
[1] "aa" "bb" "cc"
$B
[1] "aa" "bb" "cc" "dd"
我们可以unlist
将list
转换为vector
('v1'),然后根据空字符串的位置创建分组索引(!nzchar(v1)
), 删除第一个元素并在末尾附加 FALSE ,得到累积和,以便该组从出现空字符串之前的位置开始。然后,我们在 tapply
中使用它,删除向量的第一个元素并使用 group by 操作获取向量的第一个元素,用于命名 'lst2'
v1 <- unlist(lst)
i1 <- cumsum(c(!nzchar(v1)[-1], FALSE))
lst2 <- tapply(v1, i1, FUN = function(x) x[-(1:2)])
names(lst2) <- tapply(v1, i1, FUN = head, 1)
lst2
#$A
#[1] "aa" "bb" "cc"
#$B
#[1] "aa" "bb" "cc" "dd"
另一个可能的选择:
spl_vals <- c("")
idxs <- lapply(lst, function(x) as.numeric(any(spl_vals %in% x))) #Find location of split values
c_idxs <- cumsum(idxs) #Use cumsum to group sets of values
c_idxs[which(idxs==1) - 1] <- 0 #Assign the value before each split to be 0. This will be the name of the element
spl <- split(lst, c_idxs) #Split you list into (1) names of elements and (2) individual elements
newlist <- lapply(spl, function(x) unlist(x)[!unlist(x) %in% spl_vals]) #Remove any split values
nms <- names(newlist) #Extract names of list (this is just for shortening the next line of code)
setNames(newlist[nms[!nms %in% "0"]], newlist[["0"]]) #Set names of elements
$A
[1] "aa" "bb" "cc"
$B
[1] "aa" "bb" "cc" "dd"
请注意,这不会从一开始就使用 unlist
,因此如果您有多个拆分值并且您希望两个元素具有不同的类型(例如字符和整数),这会保留该类型。例如,使用:
lst <- list('A', c("", 'aa'), 'bb', 'cc', 'B', c(0, 1), 2, 3, 4)
spl_vals <- c("",0)
你得到:
$A
[1] "aa" "bb" "cc"
$B
[1] 1 2 3 4