I've got a data frame that contains names that are grouped, like so:
df <- data.frame(group = rep(letters[1:2], each=2),
name = LETTERS[1:4])
> df
group name
1 a A
2 a B
3 b C
4 b D
I would like to convert this into a list that is keyed on the group names and contains the names. Example output:
df_out <- list(a=c('A', 'B'),
b=c('C', 'D'))
> df_out
$a
[1] "A" "B"
$b
[1] "C" "D"
This is not a new question but I would like to do this wholly within the tidyverse.
There is no such function yet in the tidyverse as far as I know. Thus, you will have to write your own:
split_tibble <- function(tibble, col = 'col') tibble %>% split(., .[, col])
Then:
dflist <- split_tibble(df, 'group')
results in a list of dataframes:
> dflist $a group name 1 a A 2 a B $b group name 3 b C 4 b D > sapply(dflist, class) a b "data.frame" "data.frame"
To get the desired output, you'll have to extend the function a bit:
split_tibble <- function(tibble, column = 'col') {
tibble %>% split(., .[,column]) %>% lapply(., function(x) x[,setdiff(names(x),column)])
}
Now:
split_tibble(df, 'group')
results in:
$a [1] A B Levels: A B C D $b [1] C D Levels: A B C D
Considering the alternatives in the comments and both answers, leads to the following conclusion: using the base R alternative split(df$name, df$group)
is much wiser.
Use tidyverse
library(tidyr)
library(dplyr)
df$ID <- 1:nrow(df) # unique variable
lst <- df %>% spread(group, name) %>% select(-ID) %>% as.list()
lapply(lst, function(x) x[!is.na(x)])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With