我有一个sqlite数据库文件,其中有几列。其中一列中嵌入了一个json字典(带两个键)。我想将json列提取到r中的一个数据框中,该数据框在单独的列中显示每个键。
我试过rjson::fromjson,但它只读取第一项。我错过了什么把戏吗?
下面是一个模仿我的问题的例子:

> eg <- as.vector(c("{\"3x\": 20, \"6y\": 23}", "{\"3x\": 60, \"6y\": 50}"))
> fromJSON(eg)

$3x
[1]20个
$6y
[1]23号
所需的输出如下:
# a data frame for both variables
  3x 6y
1 20 23
2 60 50

或者,
# a data frame for each variable
  3x
1 20
2 60

  6y
1 23
2 50

最佳答案

你要找的实际上是lapplyrbind或相关应用程序的组合。
我将对您的数据进行一些扩展,使其包含两个以上的元素。

eg <- c("{\"3x\": 20, \"6y\": 23}",
        "{\"3x\": 60, \"6y\": 50}",
        "{\"3x\": 99, \"6y\": 72}")

library(jsonlite)

使用基r,我们可以
do.call(rbind.data.frame, lapply(eg, fromJSON))
#   X3x X6y
# 1  20  23
# 2  60  50
# 3  99  72

您可能会尝试执行类似于Reduce(rbind, lapply(eg, fromJSON))的操作,但显著的区别是,在Reduce模型中,rbind被称为“n-1”次,其中“n”是eg中的元素数;这会导致大量数据复制,尽管使用小的“n”可以正常工作,但它的伸缩性非常差。使用do.call选项,rbind只调用一次。
注意,列标签已经被r-ized,因为列名不应该以数字开头。(这是可能的,但通常是不鼓励的。)
如果您确信所有子字符串都将具有完全相同的元素,那么您在这里可能会很好。如果有可能在某个时候会有不同,也许
eg <- c(eg, "{\"3x\": 99}")

然后您会注意到,默认情况下,基本R解决方案不再工作。
do.call(rbind.data.frame, lapply(eg, fromJSON))
# Error in (function (..., deparse.level = 1, make.row.names = TRUE, stringsAsFactors = default.stringsAsFactors())  :
#   numbers of columns of arguments do not match

可能有一些技术可以尝试规范化元素,从而确保匹配。但是,如果您不反对data.frame包:
library(dplyr)
eg2 <- bind_rows(lapply(eg, fromJSON))
eg2
# # A tibble: 4 × 2
#    `3x`  `6y`
#   <int> <int>
# 1    20    23
# 2    60    50
# 3    99    72
# 4    99    NA

尽管不能直接用dollar方法调用它,但仍然可以使用tidyverse或backticks。
eg2$3x
# Error: unexpected numeric constant in "eg2$3"
eg2[["3x"]]
# [1] 20 60 99 99
eg2$`3x`
# [1] 20 60 99 99

关于json - rjson::fromJSON仅返回第一项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48797079/

10-09 08:39