/ / JSON Analizando una sola columna dentro de un marco de datos - json, r

JSON Analizando una sola columna dentro de un marco de datos - json, r

Estoy trabajando con datos similares a los siguientes: una lista de dispositivos y un registro de sus transacciones en formato JSON.

device_id              |                net_revenue_map
1984691C-1EC1-4743-8DC5-55D882388C29 | {"2016-12-11":3.66}
56132A1A-ACEF-4073-878B-98E62E84FDB5 | {"2016-12-10":3.493}
036DF381-72DE-4523-9576-D79FFDB33820 | {"2016-12-10":3.493}
D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 | {"2016-12-11":1.543,"2016-12-10":1.543,"2016-12-12":1.543}
E70CA4A8-D5F5-42A1-ADC4-392A2930B779 | {"2016-12-11":3.685}
E7A508A8-3517-4F5A-9876-5B7704ABD7FD | {"2016-12-11":1.393}
43BE8905-CDDF-440C-A705-C80C06D448E2 | {"2016-12-11":1.393}
CCACC621-05A9-4727-B214-730B56E49FC9 | {"2016-12-12":27.728}

Estoy intentando analizar el JSON para que se transforme en algo como lo siguiente:

              device_id              | transaction_date | Transaction_Amt
1984691C-1EC1-4743-8DC5-55D882388C29 |   2016-12-11 | 3.66
56132A1A-ACEF-4073-878B-98E62E84FDB5 | 2016-12-10 | 3.493
036DF381-72DE-4523-9576-D79FFDB33820 | 2016-12-10 | 3.493
D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 | 2016-12-11 | 1.543
D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 | 2016-12-10 | 1.543
D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 | 2016-12-12 | 1.543
E70CA4A8-D5F5-42A1-ADC4-392A2930B779 | 2016-12-11 | 3.685
E7A508A8-3517-4F5A-9876-5B7704ABD7FD | 2016-12-11 | 1.393
43BE8905-CDDF-440C-A705-C80C06D448E2 | 2016-12-11 | 1.393
CCACC621-05A9-4727-B214-730B56E49FC9 | 2016-12-12 | 27.728

cuando intento el siguiente código, aparece un error

library(jsonlite)
parse <- fromJSON(record_test[,2])
Error: parse error: trailing garbage
{"2016-12-11":3.66} {"2016-12-10":3.493} {"2016-12-
(right here) ------^

¿Necesito agregar una coma al final de cada¿columna? La mayoría de las otras respuestas para analizar JSON que estoy viendo son un marco de datos puramente JSON, pero esto contiene solo una columna de JSON dentro del marco de datos, por lo que "es donde" me encuentro con problemas.

Respuestas

2 para la respuesta № 1

Aquí está un enfoque tidyverse:

library(tidyverse)

df %>%
# read each entry into list column
mutate(json = map(net_revenue_map, jsonlite::fromJSON),
date = map(json, names),    # extract dates from list names
date = map(date, as.Date),    # convert to proper dates
amount = map(json, simplify)) %>%    # simplify list to values
unnest(date, amount) %>%    # expand list columns
select(-net_revenue_map)    # clean up

## # A tibble: 10 × 3
##                               device_id       date amount
##                                   <chr>     <date>  <dbl>
## 1  1984691C-1EC1-4743-8DC5-55D882388C29 2016-12-11  3.660
## 2  56132A1A-ACEF-4073-878B-98E62E84FDB5 2016-12-10  3.493
## 3  036DF381-72DE-4523-9576-D79FFDB33820 2016-12-10  3.493
## 4  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 2016-12-11  1.543
## 5  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 2016-12-10  1.543
## 6  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0 2016-12-12  1.543
## 7  E70CA4A8-D5F5-42A1-ADC4-392A2930B779 2016-12-11  3.685
## 8  E7A508A8-3517-4F5A-9876-5B7704ABD7FD 2016-12-11  1.393
## 9  43BE8905-CDDF-440C-A705-C80C06D448E2 2016-12-11  1.393
## 10 CCACC621-05A9-4727-B214-730B56E49FC9 2016-12-12 27.728

O base R equivalente (guardar jsonlite::fromJSON, obviamente)

df$amount <- lapply(df$net_revenue_map, jsonlite::fromJSON)
df$date <- lapply(df$amount, function(x){as.Date(names(x))})
df$amount <- lapply(df$amount, unlist)
df$net_revenue_map <- NULL

df <- do.call(rbind, apply(df, 1, data.frame))
rownames(df) <- NULL

df
##                               device_id amount       date
## 1  1984691C-1EC1-4743-8DC5-55D882388C29  3.660 2016-12-11
## 2  56132A1A-ACEF-4073-878B-98E62E84FDB5  3.493 2016-12-10
## 3  036DF381-72DE-4523-9576-D79FFDB33820  3.493 2016-12-10
## 4  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0  1.543 2016-12-11
## 5  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0  1.543 2016-12-10
## 6  D622F3F8-BEC0-4B42-AE99-B10527DFA8B0  1.543 2016-12-12
## 7  E70CA4A8-D5F5-42A1-ADC4-392A2930B779  3.685 2016-12-11
## 8  E7A508A8-3517-4F5A-9876-5B7704ABD7FD  1.393 2016-12-11
## 9  43BE8905-CDDF-440C-A705-C80C06D448E2  1.393 2016-12-11
## 10 CCACC621-05A9-4727-B214-730B56E49FC9 27.728 2016-12-12

Datos

df <- structure(list(device_id = c("1984691C-1EC1-4743-8DC5-55D882388C29",
"56132A1A-ACEF-4073-878B-98E62E84FDB5", "036DF381-72DE-4523-9576-D79FFDB33820",
"D622F3F8-BEC0-4B42-AE99-B10527DFA8B0", "E70CA4A8-D5F5-42A1-ADC4-392A2930B779",
"E7A508A8-3517-4F5A-9876-5B7704ABD7FD", "43BE8905-CDDF-440C-A705-C80C06D448E2",
"CCACC621-05A9-4727-B214-730B56E49FC9"), net_revenue_map = c("{"2016-12-11":3.66}",
"{"2016-12-10":3.493}", "{"2016-12-10":3.493}", "{"2016-12-11":1.543,"2016-12-10":1.543,"2016-12-12":1.543}",
"{"2016-12-11":3.685}", "{"2016-12-11":1.393}", "{"2016-12-11":1.393}",
"{"2016-12-12":27.728}")), .Names = c("device_id", "net_revenue_map"
), class = "data.frame", row.names = c(NA, -8L))

1 para la respuesta № 2

Enfoque alternativo tidyverse:

library(jsonlite)
library(dplyr)

rowwise(df) %>%
do(data_frame(device_id=.$device_id,
amount=unlist(fromJSON(.$net_revenue_map)),
date=names(fromJSON(.$net_revenue_map))))