Sorting lists by purrr::transpose but some value is missing

Viewed 211

I want to sort the lists depending on the number of "a" in each element.

library("purrr")
data1 <- c("apple","appreciate","available","account","adapt")
data2 <- c("tab","banana","cable","tatabox","aaaaaaa")
list1 <- list(data1,data2)
ca <- lapply(list1, function(x) str_count(x, "a"))
t2 <- Map(split, list1, ca)
t3 <- transpose(t2)
> t3
$`1`
$`1`[[1]]
[1] "apple"   "account"

$`1`[[2]]
[1] "tab"   "cable"


$`2`
$`2`[[1]]
[1] "appreciate" "adapt"     

$`2`[[2]]
[1] "tatabox"


$`3`
$`3`[[1]]
[1] "available"

$`3`[[2]]
[1] "banana"

It lost the "aaaaaaa" which in data2. How can I fix this problem?

I had find a solution:

data1 <- c("apple","appreciate","available","account","adapt")
data2 <- c("tab","banana","cable","tatabox","aaaaaaa","aaaaaaaaaaa")
list1 <- list(data1,data2)
ca <- lapply(list1, function(x) str_count(x, "a"))
k11<- flatten(Map(split, list1, ca))
k1<-split(k11, as.integer(names(k11)))
2 Answers

Citing the words of lionel: "transpose() treats lists of lists as implicitly rectangular tables". It was not designed for many edge cases like the current one. However, you could get the requried put by place the longer one at the begining: transpose(t2[2:1]).

However, this workaround could not generalize. I prefer the following way --- combine the sublists into a single list and split again:

> t3 <- do.call(c, t2)
> split(t3, names(t3))
$`1`
$`1`$`1`
[1] "apple"   "account"

$`1`$`1`
[1] "tab"   "cable"


$`2`
$`2`$`2`
[1] "appreciate" "adapt"     

$`2`$`2`
[1] "tatabox"


$`3`
$`3`$`3`
[1] "available"

$`3`$`3`
[1] "banana"


$`7`
$`7`$`7`
[1] "aaaaaaa"

Edit

A function for named and unnamed input:

data1 <- c("apple","appreciate","available","account","adapt")
data2 <- c("tab","banana","cable","tatabox","aaaaaaa","aaaaaaaaaaa")
list1 <- list(data1,data2)
names(list1) <- c("atf","bdfs")

f <- function(x){
    if(is.null(names(x))){
        names(x) <- make.names(seq_along(x))
    }
    dtf <- stack(x)
    res <- split(dtf, str_count(dtf$values, 'a'))
    lapply(res, function(y) split(y$values, y$ind, drop = TRUE) )
}

f(list1)

We can also do this using pipe with purrr functions

map(list1, str_count, "a") %>% 
        map2(list1, ., split) %>%
        flatten %>% 
        split(names(.))
#$`1`
#$`1`$`1`
#[1] "apple"   "account"

#$`1`$`1`
#[1] "tab"   "cable"


#$`2`
#$`2`$`2`
#[1] "appreciate" "adapt"     

#$`2`$`2`
#[1] "tatabox"


#$`3`
#$`3`$`3`
#[1] "available"

#$`3`$`3`
#[1] "banana"


#$`7`
#$`7`$`7`
#[1] "aaaaaaa"
Related