elliot
elliot

Reputation: 1944

Unlist/unnest for a character vector in a dataframe?

Is there a function or way unlist or unnest a vector within a dataframe using dplyr? I have the following example.

library(tidyverse)
df <- tibble(x = 
      c("c(\"Police\", \"Pensions\")",
        "c(\"potato\", \"sweetpotato\")"))
df
# A tibble: 2 x 1
  x                               
  <chr>                           
1 "c(\"Police\", \"Pensions\")"   
2 "c(\"potato\", \"sweetpotato\")"

I'd like to get that dataframe column into a format like this.

> df
# A tibble: 4 x 1
  x          
  <chr>      
1 Police     
2 Pensions   
3 Potato     
4 Sweetpotato

Upvotes: 3

Views: 1556

Answers (2)

akrun
akrun

Reputation: 887098

One option is separate_rows

library(tidyverse)
df %>% 
    separate_rows(x) %>%
    filter(!x %in% c('c', ''))
# A tibble: 4 x 1
#  x          
#  <chr>      
#1 Police     
#2 Pensions   
#3 potato     
#4 sweetpotato

NOTE: It would be faster/efficient to separate and filter


Or another option is to extract the words between th quotes and then unnest

df %>% 
   mutate(x = str_extract_all(x, '(?<=")[A-Za-z]+')) %>%
   unnest
# A tibble: 4 x 1
#  x          
#  <chr>      
#1 Police     
#2 Pensions   
#3 potato     
#4 sweetpotato

Benchmarks

On a slightly bigger data,

df1 <- df[rep(1:nrow(df), each = 1e5), ]

system.time({
df1 %>% 
    separate_rows(x) %>%
    filter(!x %in% c('c', ''))


})
#. user  system elapsed 
#  0.916   0.033   0.939 


system.time({
df1 %>%
 mutate(x = str_extract_all(x, '(?<=")[A-Za-z]+')) %>%
   unnest

})
#  user  system elapsed 
#  0.763   0.015   0.773 


system.time({

df1 %>% 
  mutate(x = map(x,~eval(parse(text=.)))) %>% 
  unnest

})
#user  system elapsed 
# 15.643   1.813  17.375 

Upvotes: 4

moodymudskipper
moodymudskipper

Reputation: 47310

As you have R code stored in strings I think it's natural to use eval(parse(text= your_input)).

Using unnest on top of it you get :

df %>% 
  mutate(x = map(x,~eval(parse(text=.)))) %>% 
  unnest

# A tibble: 4 x 1
#             x
#         <chr>
# 1      Police
# 2    Pensions
# 3      potato
# 4 sweetpotato

Upvotes: 2

Related Questions