Упрощение POSIX node с помощью RJSONIO:: fromJSON()
У меня есть следующий вектор двойных значений x
, где каждый элемент представляет собой дату POSIX
x <- c(1417621083, 1417621204, 1417621384, 1417621564, 1417621623)
Я использую пакет RJSONIO и хотел бы продолжать это делать.
Как упражнение, я хотел бы преобразовать эти значения в текст JSON, а затем снова прочитать их снова в R, но у меня возникли проблемы с получением представлений даты и времени в хороший упрощенный результат списка. В JSON даты должны быть в специальном формате, поэтому значения в x
преобразуются в следующее:
dates <- c("/new Date(1417621083)", "/Date(1417621204)", "/Date(1417621384)",
"/Date(1417621564)", "/Date(1417621623)")
Когда я запускаю dates
со вторым произвольным вектором через парсер RJSONIO, все кажется плавным.
library(RJSONIO)
make <- toJSON(list(date = dates, value = LETTERS))
Затем, когда я анализирую новый текст JSON, используя параметр stringFun
с помощью процедуры R-json C для дат, результатом является список из двух элементов, первый элемент - список, а второй - атомный вектор.
(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"
Но я ожидал список из двух векторов, и я предпочел бы его в виде
# $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"
Я попробовал несколько способов упростить результат из вызова fromJSON()
, и ни одна из них не сработала. Вот несколько моих попыток:
Использование обработчика: Это упрощает результат, но не позволяет переформатировать даты
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"
Попытка аргумента simplify
: Я пробовал несколько разных вариантов этого, и никто не работал.
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"
Есть ли способ упростить результат для дат в вызове fromJSON()
?
Ответы
Ответ 1
Я думаю, что вы не можете получить принуждение дат и их упрощение к вектору в одно и то же время. По той простой причине, что это еще не реализовано в RJSONIO
. В самом деле, как вы упомянули, упрощение выполняется с использованием одного флага: StrictLogical
, StrictNumeric
и StrictCharacter
, которые создают логические, числовые или символьные векторы. Возможно, вам следует связаться с сопровождающим, чтобы добавить флаг StrictPosixct
для дат POSIXct
.
Использование stringFun
не может помочь, поскольку оно получает скалярный элемент (символьную строку) и не знает других векторных элементов. Вы можете проверить это, определив функцию R как параметр stringFun и поместите в нее браузер.
convertJSONDate <-
function(x)
{
if(grepl('Date',x)){
val <- sub('.*[(]([0-9]+).*','\\1',x)
return(structure(as.numeric(val)/1000, class = c("POSIXct", "POSIXt")))
}
x
}
Я думаю, вы хотите сделать принуждение/упрощение, когда вы разбираете свой json по причине производительности. Я бы использовал другую стратегию:
- Я принуждаю свои числовые значения к POSIXct, и я буду хранить их как символ в хорошо отформатированных датах. Это лучше, чем специальный (уродливый) формат даты "Дата (.., дата" ) RJSONIO. Помните, что формат json - это стандартный формат, который может быть проанализирован другими языками (python, js,..)
- Затем проанализируйте мои даты как обычный символ, и я использую быстрый пакет
fasttime
, чтобы принудить его к вектору POSIXct.
вот какой код, чтобы показать это:
## 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"
Ответ 2
Из значения read
, которое я предполагаю, является желаемой отправной точкой... это один из способов:
> 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"
Класс-принуждение является "грязным", но я уже пробовал немало других (неудачных) стратегий, например. unlist
, sapply( read,"[[",1)
, sapply(read, c)
), для сохранения атрибутов, поэтому я решил спуститься в грязь с R и размахивать классом-молотом.
Ответ 3
Поскольку срок действия ресурса истек, и выясняется, что в настоящее время это невозможно сделать в RJSONIO
(или так кажется), я собираюсь использовать это как альтернативный метод, если другие пользователи столкнутся с этой проблемой и нужно решение.
Пакет jsonlite
может легко выполнить эту операцию. Все, что нам нужно сделать, это добавить класс POSIXt
к числовому вектору и указать "mongo"
для синтаксического анализатора в неэкспортируемой функции 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"