Tengo algunos datos textuales que se presentan en el siguiente formato después de leerlos en 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"

¿Existe una manera fácil de cambiar la estructura de esta lista usando "" como indicador, de modo que el elemento inmediatamente antes de "" se convierta en un encabezado de lista?

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

$A
[1] "aa" "bb" "cc"

$B
[1] "aa" "bb" "cc" "dd"
3
Sati 30 sep. 2017 a las 16:03

2 respuestas

La mejor respuesta

Podríamos unlist el list a vector ('v1'), luego crear un índice de agrupación basado en la posición de cadenas vacías (!nzchar(v1)), eliminamos el primer elemento y agregue FALSE al final, obtenga la suma acumulativa para que el grupo comience en la posición anterior a la aparición de una cadena vacía. Luego, usamos eso en tapply, eliminamos los primeros elementos del vector y usamos un grupo por operación para obtener el primer elemento del vector para nombrar el '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"
4
akrun 30 sep. 2017 a las 17:05

Otra opción potencial:

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"

Tenga en cuenta que esto no usa una unlist desde el principio, por lo que si tenía varios valores divididos y deseaba que dos elementos fueran de tipo diferente (por ejemplo, carácter y entero), esto conserva ese tipo. Por ejemplo, con:

lst <- list('A', c("", 'aa'), 'bb', 'cc', 'B', c(0, 1), 2, 3, 4)
spl_vals <- c("",0)

Usted obtiene:

$A
[1] "aa" "bb" "cc"

$B
[1] 1 2 3 4
3
Mike H. 30 sep. 2017 a las 14:36