Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unnest dataframe within dataframe R

Tags:

r

tidyverse

I would like to unnest this dataframe.

df <- tibble(
  bears = c(1,2,3),
  eagles = tibble(
    talons = c(2,3,4),
    beaks = c("x","y","z")
  )
)

So that it looks like

tibble(
  bears = c(1,2,3),
  talons = c(2,3,4),
   beaks = c("x","y","z")
)

I have tried using unnest and unnest_wider, flatten and unlist but to no avail. If I run, for example,

test <- df %>%
  unnest_wider(eagles, names_sep = "_")

The error is

Error: Assigned data `map(data[[col]], vec_to_wide, col = col, names_sep = names_sep)` must be compatible with existing data.
x Existing data has 3 rows.
x Assigned data has 2 rows.
ℹ Only vectors of size 1 are recycled.

I'm not sure how to resolve this error. Thanks!

like image 638
Nick Avatar asked Jun 10 '20 21:06

Nick


People also ask

How do I Unnest a DataFrame in R?

The tidyr package in R is used to “tidy” up the data. The unnest() method in the package can be used to convert the data frame into an unnested object by specifying the input data and its corresponding columns to use in unnesting. The output is produced in the form of a tibble in R.

What is a nested DataFrame?

A nested data frame is a data frame where one (or more) columns is a list of data frames.


2 Answers

We can use reduce with tibble

library(purrr)
df1 <- bind_cols(df[1], reduce(df[-1], tibble))
str(df1)
#tibble [3 × 3] (S3: tbl_df/tbl/data.frame)
# $ bears : num [1:3] 1 2 3
# $ talons: num [1:3] 2 3 4
# $ beaks : chr [1:3] "x" "y" "z"

Or if we need to rename

library(dplyr)
library(stringr)
df %>%
    select(where(is.tibble)) %>%
    imap_dfc(~  set_names(.x, str_c(.y, '_', names(.x)))) %>%
    bind_cols(df %>%
          select(where(negate(is.tibble))), .)
# A tibble: 3 x 3
#  bears eagles_talons eagles_beaks
#  <dbl>         <dbl> <chr>       
#1     1             2 x           
#2     2             3 y           
#3     3             4 z           

Or using

df %>%
  reduce(data.frame) 

Or an easier option is do.call in base R

df1 <- do.call(data.frame, df)
str(df1)
#'data.frame':  3 obs. of  3 variables:
# $ bears        : num  1 2 3
# $ eagles.talons: num  2 3 4
# $ eagles.beaks : chr  "x" "y" "z"
like image 122
akrun Avatar answered Oct 24 '22 17:10

akrun


Using unpack from tidyr does the job I think:

df <- tibble(
         bears = c(1,2,3),
         eagles = tibble(
             talons = c(2,3,4),
             beaks = c("x","y","z")
         )
    )
tidyr::unpack(df, cols=c(eagles))

Output:

# A tibble: 3 x 3
  bears talons beaks
  <dbl>  <dbl> <chr>
1     1      2 x    
2     2      3 y    
3     3      4 z  

If you want to keep "eagles", do

 unpack(df, cols=c(eagles), names_sep = "_")
like image 38
MR_MPI-BGC Avatar answered Oct 24 '22 18:10

MR_MPI-BGC