json r rjsonio

Simplificando un nodo POSIX con RJSONIO:: fromJSON()



(3)

Tengo el siguiente vector de valores dobles, x , donde cada elemento representa una fecha y hora POSIX

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

Estoy usando el paquete RJSONIO y me gustaría continuar haciéndolo.

Como ejercicio, me gustaría convertir estos valores en texto JSON y luego volver a leerlos en R, pero tengo problemas para obtener las representaciones de fecha y hora en un buen resultado de lista simplificada. En JSON, las fechas deben estar en un formato especial para que los valores en x se conviertan a lo siguiente:

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

Cuando ejecuto dates con un segundo vector arbitrario a través del analizador RJSONIO , todo parece ir bien.

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

Luego, cuando analizo el nuevo texto JSON utilizando la opción stringFun con la rutina R-json C para las fechas, el resultado es una lista de dos elementos, el primer elemento es una lista y el segundo un vector atómico.

(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"

Pero esperaba una lista de dos vectores, y preferiría tenerla en forma de

# $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"

Intenté varias formas de simplificar el resultado desde la llamada a fromJSON() , y ninguna de ellas ha funcionado. Aquí hay un par de mis intentos:

Usando un controlador: Esto simplifica el resultado pero falla al reformatear las fechas

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"

Probando el argumento simplify : probé varias variedades diferentes de esto y ninguna funcionó.

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"

¿Hay alguna manera de simplificar el resultado para las fechas en la llamada a fromJSON() ?


Creo que no se puede obtener la coacción de las fechas y su simplificación a un vector al mismo tiempo. Por la sencilla razón de que esto todavía no está implementado en RJSONIO . De hecho, al mencionar que la simplificación se realiza con una de las StrictLogical : StrictLogical , StrictNumeric y StrictCharacter que crean vectores lógicos, de números o de caracteres. Tal vez debería ponerse en contacto con el mantenedor para agregar el indicador POSIXct para POSIXct fechas POSIXct .

El uso de stringFun no puede ayudar porque recibe un elemento escalar (una cadena de caracteres) y no conoce otros elementos vectoriales. Puede verificar esto definiendo una función R como parámetro stringFun y colocando un navegador dentro de ella.

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

Supongo que quieres hacer la coerción / simplificación cuando analizas tu json por una razón de rendimiento. Yo usaría una estrategia diferente:

  1. Yo coacciono mis valores numéricos a un POSIXct y los almacenaré como un personaje en fechas bien formateadas. Esto es mejor que el formato de fecha especial (feo) "nueva fecha (.., fecha") RJSONIO. Recuerde que el formato json es un formato estándar que puede ser analizado por otros idiomas (python, js, ..)
  2. Luego, analice mis fechas como un personaje normal y uso el paquete fasttime de Fast Fast para forzarlo al vector POSIXct.

Aquí un código para mostrar esto:

## 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"


Dado que la recompensa ha caducado y resulta que esto no se puede hacer actualmente en RJSONIO (o eso parece), lo pondré como otro método alternativo en caso de que otros usuarios encuentren este problema y necesiten una solución.

El paquete jsonlite puede hacer esta operación fácilmente. Todo lo que tenemos que hacer es agregar la clase POSIXt al vector numérico y especificar "mongo" para el analizador en la función no exportada como 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"


Desde el valor de read que supongo es el punto de inicio deseado ... esta es una forma:

> 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"

La coerción de clase es un poco "sucia", pero ya había probado algunas otras estrategias (fallidas), por ejemplo, sapply( read,"[[",1) , sapply( read,"[[",1) , sapply(read, c) ), para preservar atributos Así que decidí meterme en el barro con R y hacer girar el martillo de la clase.