2014-12-05 15 views
20

Ho il seguente vettore di valori doppi, x, dove ogni elemento rappresenta un POSIX data tempoSemplificando un nodo POSIX con RJSONIO :: fromJSON()

x <- c(1417621083, 1417621204, 1417621384, 1417621564, 1417621623) 

Sto usando il pacchetto RJSONIO, e vorrei continuare a farlo.

Come esercizio, mi piacerebbe convertire questi valori in testo JSON e poi leggerli di nuovo in R di nuovo, ma sto avendo problemi a ottenere le rappresentazioni di data e ora in un risultato di lista semplificata. In JSON, le date devono essere in un formato speciale in modo che i valori in x vengono convertiti al seguente:

dates <- c("/new Date(1417621083)", "/Date(1417621204)", "/Date(1417621384)", 
      "/Date(1417621564)", "/Date(1417621623)") 

Quando eseguo dates con un secondo vettore arbitrario attraverso il RJSONIO parser, tutto sembra andare senza intoppi.

library(RJSONIO) 
make <- toJSON(list(date = dates, value = LETTERS)) 

Quando poi analizzare il nuovo testo JSON utilizzando l'opzione stringFun con il C routine di R-json per date, il risultato è una lista a due elementi, il primo elemento essendo un elenco e il secondo un vettore atomico .

(read <- fromJSON(make, stringFun = "R_json_dateStringOp")) 
# $date 
# $date[[1]] 
# [1] "2014-12-03 07:38:03 PST" 
# 
# $date[[2]] 
# [1] "2014-12-03 07:40:04 PST" 
# 
# $date[[3]] 
# [1] "2014-12-03 07:43:04 PST" 
# 
# $date[[4]] 
# [1] "2014-12-03 07:46:04 PST" 
# 
# $date[[5]] 
# [1] "2014-12-03 07:47:03 PST" 
# 
# 
# $value 
# [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" 
# [14] "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 

ma mi aspettavo un elenco di due vettori, e avrei preferito averlo in forma di

# $date 
# [1] "2014-12-03 07:38:03 PST" "2014-12-03 07:40:04 PST" 
# [3] "2014-12-03 07:43:04 PST" "2014-12-03 07:46:04 PST" 
# [5] "2014-12-03 07:47:03 PST" 
# 
# $value 
# [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" 
# [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 

Ho provato diversi modi per semplificare il risultato all'interno della chiamata a fromJSON(), e nessuno di loro ha funzionato. Qui ci sono un paio di miei tentativi:

Utilizzando un gestore: Questo semplifica il risultato, ma non riesce a riformattare le date

h1 <- basicJSONHandler(simplify = TRUE) 
fromJSON(make, handler = h1, stringFun = "R_json_dateStringOp") 
# $date 
# [1] "/new Date(1417621083)" "/Date(1417621204)"  
# [3] "/Date(1417621384)"  "/Date(1417621564)"  
# [5] "/Date(1417621623)"  
# 
# $value 
# [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" 
# [14] "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 

Cercando l'argomentosimplify: Ho provato diverse varietà di questo e nessuno ha funzionato.

fromJSON(make, simplify = StrictCharacter) 
# $date 
# [1] "/new Date(1417621083)" "/Date(1417621204)"  
# [3] "/Date(1417621384)"  "/Date(1417621564)"  
# [5] "/Date(1417621623)"  
# 
# $value 
# [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" 
# [14] "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 

C'è un modo per semplificare il risultato per le date nella chiamata a fromJSON()?

risposta

5

Penso che non si possa ottenere la coercizione delle date e la loro semplificazione in un vettore nello stesso tempo. Per la semplice ragione che questo non è (ancora) implementato in RJSONIO. Infatti, come si menziona la semplificazione viene eseguita utilizzando uno flag: StrictLogical, StrictNumeric e StrictCharacter che creano logici, numeri o caratteri vettori. Forse dovresti contattare il manutentore per aggiungere il flag StrictPosixct per le date POSIXct.

L'utilizzo di non può essere d'aiuto perché riceve un elemento scalare (una stringa di caratteri) e non è a conoscenza di altri elementi vettoriali. Puoi verificarlo definendo una funzione R come parametro stringFun e inserendo un browser.

convertJSONDate <- 
    function(x) 
    { 
    if(grepl('Date',x)){ 
     val <- sub('.*[(]([0-9]+).*','\\1',x) 
     return(structure(as.numeric(val)/1000, class = c("POSIXct", "POSIXt"))) 
    } 
    x 
    } 

Immagino che tu voglia fare la coercizione/semplificazione quando analizzi il tuo json per un motivo prestazionale. Vorrei utilizzare una strategia diversa:

  1. I coerce i miei valori numerici su POSIXct e li memorizzerò come un carattere in date ben formattate. Questo è meglio dello speciale (brutto) "nuovo Data (.., data") formato di data RJSONIO. Ricorda che il formato JSON è un formato standard che può essere analizzato da altri linguaggi (python, js, ..)
  2. Quindi analizzare le mie date come un carattere normale e io uso il pacchetto veloce fasttime per costringerlo al vettore POSIXct.

qui un po 'di codice per mostrare questo:

## coerce x to dates a well formatted dates 
dd <- as.character(as.POSIXct(x,origin = '1970-01-01' , tz = "UTC")) 
## read it again in a fast way 
fastPOSIXct(fromJSON(make)$date) 

[1] "2014-12-03 16:38:03 CET" "2014-12-03 16:40:04 CET" "2014-12-03 16:43:04 CET" "2014-12-03 16:46:04 CET" "2014-12-03 16:47:03 CET" 
3

Dal valore read che sto cercando di indovinare è il punto di partenza desiderato ... questo è un modo:

> dd <- sapply(read, c) 
> class(dd) <- "POSIXct" 
> dd 
[1] "2014-12-03 07:38:03 PST" "2014-12-03 07:40:04 PST" "2014-12-03 07:43:04 PST" 
[4] "2014-12-03 07:46:04 PST" "2014-12-03 07:47:03 PST" 

Class-coercizione è una specie di "sporco" ma io avevo già provato un bel po ' altre strategie (fallite), ad es unlist, sapply(read,"[[",1), sapply(read, c)), per preservare gli attributi, così ho deciso di scendere nel fango con R e far oscillare il martello della classe.

0

Poiché la taglia è scaduta e si scopre che al momento non è possibile farlo in RJSONIO (o così sembra), ho intenzione di mettere questo come un altro metodo alternativo nel caso in cui altri utenti si imbattano in questo problema e bisogno di una soluzione.

Il pacchetto jsonlite può eseguire facilmente questa operazione.Tutto ciò che dobbiamo fare è aggiungere la classe POSIXt al vettore numerico e specificare "mongo" per il parser nella funzione non esportata asJSON.

# unloadNamespace(RJSONIO) ## to avoid confusion between packages 
library(jsonlite)  

x <- c(1417621083, 1417621204, 1417621384, 1417621564, 1417621623) 

class(x) <- "POSIXt"  

data <- list(dates = x, values = letters[1:5]) 

json <- jsonlite:::asJSON(data, POSIXt = "mongo") 

fromJSON(json) 
# $dates 
# [1] "2014-12-03 07:38:03 PST" "2014-12-03 07:40:04 PST" 
# [3] "2014-12-03 07:43:04 PST" "2014-12-03 07:46:04 PST" 
# [5] "2014-12-03 07:47:03 PST" 
# 
# $values 
# [1] "a" "b" "c" "d" "e"