Last active
June 28, 2018 16:59
-
-
Save alandipert/ba3f925a31c67cd08966ad4ea220e541 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Like Map but expects f to return a list and concatenates results. | |
Mapcan <- function(f, xs) Reduce(append, Map(f, xs)) | |
# Returns a list of named lists, each with `name` and `value` values, for the | |
# given named list. | |
as_entries <- function(named_list) { | |
Map(function(name) list(key = name, val = named_list[[name]]), names(named_list)) | |
} | |
# Returns a list of lists, each starting with the leaf value and followed by the path to that leaf. | |
paths <- function(parent, x) { | |
if (typeof(x) == "list") { | |
# Named list aka JSON object | |
if (!is.null(names(x))) { | |
Mapcan(function(entry) { | |
paths(c(parent, entry$key), entry$val) | |
}, as_entries(x)) | |
# Unnamed list aka JSON array | |
} else if (length(x) > 0) { | |
Mapcan(function(i) { | |
paths(c(parent, i), x[[i]]) | |
}, 1:length(x)) | |
} | |
} else { | |
# Leaf, so return the leaf value followed by its path | |
list(c(list(x), parent)) | |
} | |
} | |
# Returns a data frame where each row is a distinct path into a tree of lists, | |
# such as that produced by jsonlite::fromJSON. Useful for querying deeply-nested | |
# structures in a tabular fashion. | |
tree_df <- function(tree) { | |
ps <- paths(list(), tree) | |
# Ensure rows are all the same length, with NA for padding | |
longest <- max(unlist(Map(length, ps))) | |
padded <- Map(function(path) { | |
c(as.list(path), rep(NA, longest-length(path))) | |
}, ps) | |
as.data.frame(do.call(rbind, padded)) | |
} | |
# Terrible data | |
stuff <- list( | |
alan = list( | |
type = "person", | |
percent_water = 70 | |
), | |
bob = list( | |
type = "rock", | |
percent_rock = 100 | |
) | |
) | |
# Find names of any items made out of more than 80% of something | |
df <- tree_df(stuff) | |
df <- subset(df, sapply(df$V1, is.numeric)) | |
item_names <- subset(df, df$V1 > 80)[,"V2"] | |
# item_names = list("bob") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment