Ich möchte Code für das tidyjson-Paket in einer Funktion wie folgt schreiben:

> enter_object(object) %>%    spread_values(
>     varnames[1] = jstring(strings[1]),
>     varnames[2] = jstring(strings[2]),
>     varnames[3] = jstring(strings[3])   )

Dieser Code läuft gut, wenn ich eine Literalzeichenfolge wie foo anstelle von varnames[1] habe. Ich möchte jedoch, dass die Funktion flexibler ist, damit ich viele Variablennamen generieren und nicht alle von Hand schreiben kann. Die Variablennamen enden als Namen für Datenrahmenspalten. Mit meinem aktuellen Fehler bekomme ich:

+         enter_object(object) %>% 
+         spread_values(
+           varnames[[1]] = jstring(strings[1]),
Error: unexpected '=' in:
"        spread_values(
          varnames[[1]] ="
>           varnames[2] = jstring(strings[2]),
Error: unexpected ',' in "          varnames[2] = jstring(strings[2]),"
>           varnames[3] = jstring(strings[3])
Error in prep_path(...) : object 'strings' not found
>         ) 
Error: unexpected ')' in "        )"

Ich kann nicht herausfinden, welche Art von Objekt vor das = gestellt werden soll, damit das = erkannt wird.


Hier ist ein Spielzeugbeispiel mit MrFlicks Lösung:

> sample_json <- '[
+     {
+         "id": 10097652,
+         "members": 2386,
+         "category": {
+             "id": 23,
+             "name": "Outdoors & Adventure",
+             "shortname": "Outdoors"
+         }   
+   }
+ ]'
> 
> group_category1 <- sample_json %>%  as.tbl_json %>% 
+     gather_array %>%  #gather_keys %>% 
+     spread_values(
+       group_id = jstring("id")
+   ) %>%
+       enter_object("category") %>% 
+       spread_values(
+         category_id = jstring("id"),
+         category_name = jstring("name"),
+         category_short_name = jstring("shortname")
+       ) 
> head(group_category1)
  document.id array.index group_id category_id        category_name category_short_name
1           1           1 10097652          23 Outdoors & Adventure            Outdoors
> 
> my_spread_values <- function(x, names, values) { 
+     stopifnot(length(names) == length(values))
+     do.call("spread_values", c(list(x), setNames(as.list(values), names )))
+  } 
> varnames <-  c("category_id", "category_name", "category_shortname")
> strings <-  c("id", "name", "shortname")
> 
> group_category2 <- sample_json %>%  as.tbl_json %>% 
+   gather_array %>% 
+   spread_values(group_id = jstring("id")) %>% 
+ enter_object("category") %>% my_spread_values( 
+     varnames, list(jstring(strings[1]), jstring(strings[2]), jstring(strings[3]) ) )
> head(group_category2)
  document.id array.index group_id category_id        category_name category_shortname
1           1           1 10097652          23 Outdoors & Adventure           Outdoors
> 

Und das funktioniert perfekt! (Einmal wurden einige nachlässige Fehler behoben, die ich gemacht hatte!)

r
4
John David Smith 28 Dez. 2015 im 00:06

1 Antwort

Beste Antwort

Hier ist eine Variante, die dem Beispiel von @ MrFlick folgt, das ich jetzt verwende:

my_spread_values <- function(x, names_list, string_type) {
  # A wrapper for "spread_values" that taks a list of names and a string type. Easier to read and much less code.
  do.call("spread_values",
    c(list(x), setNames(lapply(names_list, string_type), as.list(names_list) ) ) )
}

Mit einer URL, die gemäß der Dokumentation hier definiert ist: http://www.meetup.com/meetup_api/docs/

raw_contents <- GET(url = url)
json_raw <- httr::content(raw_contents, type = "text")
json_contents <- sub('^\\{"results":\\[', "[", json_raw)
json_contents <- sub('\\],"meta"\\:\\{.*\\}.$', "]",json_contents)
my_tbl_json <- gsub('\\\\/', "/",json_contents)  %>% as.tbl_json

num_array <- c("created", "id", "lat", "lon", "members", "score")

group_numerics <- my_tbl_json %>% 
  gather_array %>% 
  my_spread_values(num_array, jnumber )  %>% 
  select(-document.id)
group_numerics$created <- as.POSIXct(group_numerics$created/1000, origin = "1970-01-01")

Ein ausführlicheres Beispiel ist dieser Satz von Arbeitscode, der das tidyjson-Paket verwendet, um Daten aus echten API-Daten zu verarbeiten Quelle.

0
John David Smith 23 Feb. 2016 im 20:24