jamse
jamse

Reputation: 354

Extract a dataframe from a column of dataframes (tidyverse approach)

I have been able to do some nice things with purrr to be able to work with dataframe columns within a dataframe. By which I am referring to a column of a dataframe where every cell contains a dataframe itself.

I am trying to find out the idiomatic approach for extracting one of these dataframes back out.

Example

# Create a couple of dataframes:
df1 <- tibble::tribble(~a, ~b,
                        1,  2,
                        3,  4)
df2 <- tibble::tribble(~a, ~b,
                       11, 12,
                       13, 14)

# Make a dataframe with a dataframe column containing 
# our first two dfs as cells:
meta_df <- tibble::tribble(~df_name, ~dfs, 
                           "One",     df1, 
                           "Two",     df2)

My question is, what is the tidyverse-preferred way of getting one of these dataframes back out of meta_df? Say I get the cell I want using select() and filter():

library("magrittr")
# This returns a 1x1 tibble with the only cell containing the 2x2 tibble that
# I'm actually after:
meta_df %>%
  dplyr::filter(df_name == "Two") %>%
  dplyr::select(dfs)

This works, but seems non-tidyverse-ish:

# To get the actual tibble that I'm after I can wrap the whole lot in brackets
# and then use position [[1, 1]] index to get it:
(meta_df %>%
  dplyr::filter(df_name == "Two") %>%
  dplyr::select(dfs))[[1, 1]]

# Or a pipeable version:
meta_df %>%
  dplyr::filter(df_name == "Two") %>%
  dplyr::select(dfs) %>%
  `[[`(1, 1)

I have a feeling that this might be a situation where the answer is in purrr rather than dplyr, and that it might be a simple trick once you know it, but I'm coming up blank so far.

Upvotes: 3

Views: 798

Answers (1)

twedl
twedl

Reputation: 1648

better solution:

Use tidyr::unnest():

meta_df %>%
  dplyr::filter(df_name == "Two") %>%
  dplyr::select(dfs) %>%
  tidyr::unnest()

other solution:

You can use pull (the tidyverse way to select the column, equivalent to $), but it returns a one-element list of tibbles, so you need to add %>% .[[1]] to the end.

meta_df %>%
  dplyr::filter(df_name == "Two") %>%
  dplyr::pull(dfs) %>% .[[1]]

Upvotes: 4

Related Questions