Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: New keep_empty = FALSE argument to list_c() and list_rbind() #1096

Closed
krlmlr opened this issue Aug 20, 2023 · 5 comments
Closed

FR: New keep_empty = FALSE argument to list_c() and list_rbind() #1096

krlmlr opened this issue Aug 20, 2023 · 5 comments
Labels
feature a feature request or enhancement tidy-dev-day 🤓 Tidyverse Developer Day rstd.io/tidy-dev-day

Comments

@krlmlr
Copy link
Member

krlmlr commented Aug 20, 2023

I'm looking for the following behavior so that I can use pivot_wider() %>% mutate(across(..., ~ list_c(.x, keep_empty = TRUE))) as a more robust replacement for tidyr::spread(convert = TRUE) .

I can achieve it today with the lower-level list_unchop(), in a very clumsy way.

library(purrr)

# Existing behavior:
list_c(list("a", NULL, "b"))
#> [1] "a" "b"
vctrs::list_unchop(list("a", NULL, "b"))
#> [1] "a" "b"
vctrs::list_unchop(list("a", NULL, "b"), indices = as.list(1:3))
#> [1] "a" NA  "b"

# I'd like to write this:
list_c(list("a", NULL, "b"), keep_empty = TRUE)
#> [1] "a" NA  "b"

Created on 2023-08-20 with reprex v2.0.2

@hadley
Copy link
Member

hadley commented Nov 1, 2023

Hmmmm, this doesn't feel quite right for purrr, but maybe it's the least worst place?

@hadley hadley added the feature a feature request or enhancement label Nov 1, 2023
@hadley hadley changed the title FR: New keep_empty = FALSE argument to list_c() FR: New keep_empty = FALSE argument to list_c() and list_rbind() Jul 15, 2024
@hadley hadley added the tidy-dev-day 🤓 Tidyverse Developer Day rstd.io/tidy-dev-day label Jul 15, 2024
@hadley
Copy link
Member

hadley commented Jul 15, 2024

I think the way to implement this for both list_c() and list_rbind() is to replace any list elements that are identical to NULL with NA. Then the vctrs machinery can take over and ensure that the output gets a missing value of the correct type.

@krlmlr
Copy link
Member Author

krlmlr commented Jul 16, 2024

The original use case was a data set with a column with varying-type data.

library(tidyverse)

variant_data <- tibble(
  key = c(1, 1, 2, 2),
  name = letters[c(1:2, 1:2)],
  value = list("a", 1, NULL, NULL)
)

variant_data |>
  pivot_wider()
#> # A tibble: 2 × 3
#>     key a         b        
#>   <dbl> <list>    <list>   
#> 1     1 <chr [1]> <dbl [1]>
#> 2     2 <NULL>    <NULL>

# How to achieve this output:
tibble(
  key = c(1, 2),
  a = c("a", NA),
  b = c(1, NA),
)
#> # A tibble: 2 × 3
#>     key a         b
#>   <dbl> <chr> <dbl>
#> 1     1 a         1
#> 2     2 <NA>     NA

Created on 2024-07-16 with reprex v2.1.0

@DavisVaughan
Copy link
Member

I've come back to look at @krlmlr's original example. It's just unchop(keep_empty = TRUE)

library(tidyverse)

variant_data <- tibble(
  key = c(1, 1, 2, 2),
  name = letters[c(1:2, 1:2)],
  value = list("a", 1, NULL, NULL)
)

variant_data |>
  pivot_wider() |>
  unchop(c(a, b), keep_empty = TRUE)
#> # A tibble: 2 × 3
#>     key a         b
#>   <dbl> <chr> <dbl>
#> 1     1 a         1
#> 2     2 <NA>     NA

So now I'm questioning if list_c() and friends really should get this argument or not.

The other thing that is nice about unchop() over forcing list_c() here is that list_c(keep_empty = TRUE) would only work on this:

variant_data |>
  pivot_wider()
#> # A tibble: 2 × 3
#>     key a         b        
#>   <dbl> <list>    <list>   
#> 1     1 <chr [1]> <dbl [1]>
#> 2     2 <NULL>    <NULL>

If those list elements are size 1. Otherwise it won't recycle to the right size. unchop() is a better tool for the job here because it gets the whole data frame and can handle any recycling that's required (like if it was <chr [2]> for example).

@DavisVaughan
Copy link
Member

See #1144 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement tidy-dev-day 🤓 Tidyverse Developer Day rstd.io/tidy-dev-day
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants