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

revisit: transpose() doesn't work as expected when inner keys are disjoint #318

Closed
jennybc opened this issue Apr 29, 2017 · 7 comments
Closed

Comments

@jennybc
Copy link
Member

jennybc commented Apr 29, 2017

Deliberately repeating name of #205. I'm not sure #205 really was a duplicate of #164.

transpose() seems to work just fine with names, so this is not about position. But it only seems to consult the first object to determine inner keys.

library(purrr)

ll <- list(
  list(x = 1, y = "one"),
  list(z = "deux", x = 2)
)

## only x and y appear, but what about z?
transpose(ll)
#> $x
#> $x[[1]]
#> [1] 1
#> 
#> $x[[2]]
#> [1] 2
#> 
#> 
#> $y
#> $y[[1]]
#> [1] "one"
#> 
#> $y[[2]]
#> NULL

## I expected this
list(
  x = map(ll, "x"),
  y = map(ll, "y"),
  z = map(ll, "z")
)
#> $x
#> $x[[1]]
#> [1] 1
#> 
#> $x[[2]]
#> [1] 2
#> 
#> 
#> $y
#> $y[[1]]
#> [1] "one"
#> 
#> $y[[2]]
#> NULL
#> 
#> 
#> $z
#> $z[[1]]
#> NULL
#> 
#> $z[[2]]
#> [1] "deux"
@jennybc jennybc changed the title revisit: transpose() doesn't work as expected when inners keys are disjoint revisit: transpose() doesn't work as expected when inner keys are disjoint Apr 29, 2017
@hadley
Copy link
Member

hadley commented May 2, 2017

Have a look at the new .names argument 😉

@jennybc
Copy link
Member Author

jennybc commented May 2, 2017

OK great!

The lists I'm dealing with are large and I don't know in advance how all the children are named. So I would have to pre-map names(), reduce with union, and then provide that to .names. It feels like it would be handy to get some help from a default along those lines.

Here's how I am doing this task by hand right now (not a reprex, sorry ... just copy/paste). I make some effort to get a decent global order for the names:

## determine the names of sub-items and a consensus order
## get vector of names for each endpoint
nms_list <- endpoints %>%
  map(names)
## union of names across endpoints
nms_glop <- nms_list %>%
  reduce(union)
## reach a consensus on name order
nms_rksum <- nms_list %>%
  map_dfc(~ match(nms_glop, .x)) %>% 
  rowSums(na.rm = TRUE)
nms <- nms_glop[order(nms_rksum)]

@hadley
Copy link
Member

hadley commented May 2, 2017

What's the principle behind the global order?

@jennybc
Copy link
Member Author

jennybc commented May 2, 2017

It's the order most consistent with how the names appear in the children of the input list, based on rank sum. If they always appear in same order, it will be that. In my current example, there is variation across the children in which names appear at all and in their order.

A simpler approach would be to just take the unique values from the union of the names. I had to reorder mine manually anyway, so maybe it's not worth trying to be clever.

@hadley
Copy link
Member

hadley commented May 2, 2017

Yeah, I'd think x %>% map(names) %>% reduce(union) would usually be sufficient. Maybe that's worth including as an example?

@jennybc
Copy link
Member Author

jennybc commented May 2, 2017

Maybe that's worth including as an example?

If it's not destined to be the default, then yes I think that would be great. Do you want me to do in a PR?

@hadley
Copy link
Member

hadley commented May 2, 2017

Yes please!

@hadley hadley closed this as completed in d4d84fe May 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants