-
Notifications
You must be signed in to change notification settings - Fork 275
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
flatten_names() #525
Comments
Or should this be an argument to |
Hey, I was about to open an issue after needing something related, but I can see it's already been thought about :) Feel free to tell if this is not related, I can open another issue. I think an extra argument to flatten would be nice (maybe Here is a minimal reprex of my use case : I'm requesting an API, which return nested JSON. Let's say the result is: {
"object": {
"colors": {
"blue": 1,
"green": 2,
"brown": 3
},
"animals": {
"cat": 4,
"mouse": 4,
"dog": 6
}
}
} Which would be the R equivalent of res <- list(
object = list(
colors = list(
blue = 1,
green = 2,
brown = 3
),
animals = list(
cat = 4,
mouse = 5,
dog = 6
)
)
) I want to turn this into a data.frame, but I want to keep the information that "blue" is in the "color" sublist (in my case it has meaning to keep the middle names), and this is lost when using flatten : map_df(res, flatten_df)
# A tibble: 2 x 6
blue green brown cat mouse dog
<int> <int> <int> <int> <int> <int>
1 1 2 3 4 4 6 While what I would want is to have something like flatten_df(res[[1]], keep_names = TRUE, sep = "_") %>% names()
[1] "colors_blue" "colors_green" "colors_brown" "animals_cat" "animals_mouse" "animals_dog" So now I'm handling is with : map_df(res, ~ tibble(
colors_blue = .x$colors$blue,
colors_green = .x$colors$green,
colors_brown = .x$colors$brown,
animals_cat = .x$animals$cat,
animals_mouse = .x$animals$mouse,
animals_dog = .x$animals$dog,
))
But it's unefficient and would fail if at some point the JSON structure changes. And this would also make sense on this kind of cases : l <- list(
a = list(
b = 12
),
c = list(
b = 13
)
)
flatten(l)
$b
[1] 12
$b
[1] 13 |
I don't know if you would prefer a C implementation or handling this in R, but here is a suggestion : # Calling devtools loal all so I can .Call
devtools::load_all("~/Seafile/documents_colin/R/purrr/")
#> Loading purrr
flatten <- function(.x, keep_names = FALSE, sep = "_") {
# Handling unnamed list & keep_names = TRUE
if (keep_names & all(is.null(names(.x)))) {
abort("You can't keep names of an unnamed list")
}
res <- .Call(flatten_impl, .x)
if (keep_names) {
nm <- paste(names(.x), map_chr(.x, names), sep = sep)
return(set_names(res, nm))
}
res
}
l <- list(
a = list(
b = 12
),
c = list(
b = 13
)
)
flatten(l)
#> $b
#> [1] 12
#>
#> $b
#> [1] 13
flatten(l, keep_names = TRUE)
#> $a_b
#> [1] 12
#>
#> $c_b
#> [1] 13
flatten(l, keep_names = TRUE, sep = "@")
#> $`a@b`
#> [1] 12
#>
#> $`c@b`
#> [1] 13
x <- rerun(2, sample(4))
flatten(x)
#> [[1]]
#> [1] 2
#>
#> [[2]]
#> [1] 3
#>
#> [[3]]
#> [1] 4
#>
#> [[4]]
#> [1] 1
#>
#> [[5]]
#> [1] 4
#>
#> [[6]]
#> [1] 2
#>
#> [[7]]
#> [1] 3
#>
#> [[8]]
#> [1] 1
flatten(x, keep_names = TRUE)
#> Error: You can't keep names of an unnamed list (I removed the backtrack from the output) Created on 2019-01-10 by the reprex package (v0.2.1) Would be happy to work on this and PR if you think this is a good idea. |
Closing because we're moving towards an approach using |
To provide a way of combining names prior to flattening:
The definition would be
So this would work as well:
The text was updated successfully, but these errors were encountered: