如何处理 jsonlite 中的缺失值?

How to deal with missing values in jsonlite?

我正在处理来自重复测量设计的数据。数据由 4 个测量组成,每个测量大约 100 个变量。这些变量之一是包含反应任务结果的 JSON 数组。这个数组的结构基本上是这样的:[[素数,答案,反应时间],[素数,答案,反应时间],...]

每个数组包含大约 80 个试验。我的目标是将此数组转换为单独的列,使其看起来像下面的示例:

prime1    answer1     reaction_time1    prime2     answer2   reaction_time2 ...
picture8  2           2398              2          1         1856
picture8  1           798               1          2         712
...

在处理示例数据集时,我设法使用以下代码将数组转换为数据帧:

reaction_data <- data.frame(example_data$ID, example_data$TP,
                       jsonlite::stream_in(textConnection(gsub("\n", "", example_data$reaction_raw))))  

如上所述,我现在正在处理以长格式排列的重复测量数据。因此,对于每个人 ID 我有四个测量值 TP,理想情况下,所有 100 个变量的完整数据集,包括 JSON 数组。但是,实际上,我当然要处理辍学和缺失值。这意味着在某些情况下 JSON 数组也会丢失。假装我的 JSON-array 只包含 3 个试验,我当前的数据框看起来或多或少像下面的示例数据(忽略所有其他变量):

ID       TP         reaction_raw
1        1          [[picture8, 2, 2398], [picture2, 1, 1856], [picture1, 1, 897]]
1        2          [[picture8, 1, 798], [picture2, 2, 712], [picture1, 1, 423]]
1        3          NA
1        4          [[picture8, 1, 1278], [picture2, 1, 1712], [picture1, 1, 902]]
2        1          [[picture8, 2, 2015], [picture2, 1, 3820], [picture1, 2, 2719]]
2        2          [[picture8, 2, 3219], [picture2, 2, 1920], [picture1, 1, 1298]]
2        3          NA
2        4          NA
3        1          [[picture8, 1, 209], [picture2, 1, 382], [picture1, 2, 891]]
3        2          NA
3        3          [[picture8, 2, 781], [picture2, 1, 291], [picture1, 1, 2039]]
3        4          NA
...

当 运行 现在我的代码时,我收到以下错误消息:

lexical error: invalid char in json text.
                                       NA
                     (right here) ------^

我想我的代码无法处理丢失的数组。有人知道如何处理这个问题吗? 提前致谢!

假设示例中缺少引号(否则解析器不会在没有抱怨的情况下通过 picture8 的第一次出现),处理此问题的方法是添加适当格式的 json 字符串,将转换为所需数据结构中的 NA 个条目。

因此,例如,假设您的数据如下所示:

df
#> # A tibble: 12 x 3
#>       ID    TP reaction_raw                                                     
#>    <int> <int> <chr>                                                            
#>  1     1     1 "[[\"picture8\", 2, 2398], [\"picture2\", 1, 1856], [\"picture1\~
#>  2     1     2 "[[\"picture8\", 1, 798], [\"picture2\", 2, 712], [\"picture1\",~
#>  3     1     3  <NA>                                                            
#>  4     1     4 "[[\"picture8\", 1, 1278], [\"picture2\", 1, 1712], [\"picture1\~
#>  5     2     1 "[[\"picture8\", 2, 2015], [\"picture2\", 1, 3820], [\"picture1\~
#>  6     2     2 "[[\"picture8\", 2, 3219], [\"picture2\", 2, 1920], [\"picture1\~
#>  7     2     3  <NA>                                                            
#>  8     2     4  <NA>                                                            
#>  9     3     1 "[[\"picture8\", 1, 209], [\"picture2\", 1, 382], [\"picture1\",~
#> 10     3     2  <NA>                                                            
#> 11     3     3 "[[\"picture8\", 2, 781], [\"picture2\", 1, 291], [\"picture1\",~
#> 12     3     4  <NA>

然后你可以用 null 参数写一个 json 作为缺失值,然后写在 reaction_rawNA:

的地方
nulljson <- "[[\"picture8\", null, null], 
              [\"picture2\", null, null], 
              [\"picture1\", null, null]]"

df$reaction_raw[is.na(df$reaction_raw)] <- nulljson

现在您可以将 json 调整为单独的列...

parser        <- function(x) as.vector(t(jsonlite::fromJSON(x)))
result_matrix <- do.call(rbind, lapply(df$reaction_raw, parser))
result_df     <- as.data.frame(result_matrix)
col_names     <- c("prime", "answer", "reaction_time")
col_names     <- paste0(col_names, rep(1:3, each = ncol(result_df)/3))
result_df     <- setNames(result_df,col_names)

...并将它们加入您的主数据框:

cbind(df[1:2], result_df)
#>    ID TP   prime1 answer1 reaction_time1   prime2 answer2 reaction_time2
#> 1   1  1 picture8       2           2398 picture2       1           1856
#> 2   1  2 picture8       1            798 picture2       2            712
#> 3   1  3 picture8    <NA>           <NA> picture2    <NA>           <NA>
#> 4   1  4 picture8       1           1278 picture2       1           1712
#> 5   2  1 picture8       2           2015 picture2       1           3820
#> 6   2  2 picture8       2           3219 picture2       2           1920
#> 7   2  3 picture8    <NA>           <NA> picture2    <NA>           <NA>
#> 8   2  4 picture8    <NA>           <NA> picture2    <NA>           <NA>
#> 9   3  1 picture8       1            209 picture2       1            382
#> 10  3  2 picture8    <NA>           <NA> picture2    <NA>           <NA>
#> 11  3  3 picture8       2            781 picture2       1            291
#> 12  3  4 picture8    <NA>           <NA> picture2    <NA>           <NA>
#>      prime3 answer3 reaction_time3
#> 1  picture1       1            897
#> 2  picture1       1            423
#> 3  picture1    <NA>           <NA>
#> 4  picture1       1            902
#> 5  picture1       2           2719
#> 6  picture1       1           1298
#> 7  picture1    <NA>           <NA>
#> 8  picture1    <NA>           <NA>
#> 9  picture1       2            891
#> 10 picture1    <NA>           <NA>
#> 11 picture1       1           2039
#> 12 picture1    <NA>           <NA>

使用的数据

df <- structure(list(ID = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 
3L, 3L), TP = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L
), reaction_raw = c(
"[[\"picture8\", 2, 2398], [\"picture2\", 1, 1856], [\"picture1\", 1, 897]]", 
"[[\"picture8\", 1, 798], [\"picture2\", 2, 712], [\"picture1\", 1, 423]]", 
NA, "[[\"picture8\", 1, 1278], [\"picture2\", 1, 1712], [\"picture1\", 1, 902]]", 
"[[\"picture8\", 2, 2015], [\"picture2\", 1, 3820], [\"picture1\", 2, 2719]]", 
"[[\"picture8\", 2, 3219], [\"picture2\", 2, 1920], [\"picture1\", 1, 1298]]", 
NA, NA, "[[\"picture8\", 1, 209], [\"picture2\", 1, 382], [\"picture1\", 2, 891]]", 
NA, "[[\"picture8\", 2, 781], [\"picture2\", 1, 291], [\"picture1\", 1, 2039]]", 
NA)), row.names = c(NA, -12L), class = c("tbl_df", "tbl", "data.frame"
))

reprex package (v0.3.0)

于 2020-07-07 创建