【问题标题】:gather the json file into long csv file将 json 文件收集到长 csv 文件中
【发布时间】:2019-12-25 10:28:14
【问题描述】:

我想将一个 json 文件转换成一个长的 csv 文件。而且我的 json 文件有数百万行的不同列。是否可以使用 R 完成它?顺便说一句,我可以访问 Sparklyr,这会有帮助吗?

json 文件如下所示:

[

{"num":"1","A":"a","B":"b"},

{"num":"2","C":"c"},

{"num":"3","D":"d"},

]

我想得到一个如下所示的 csv 文件:

数字、键、值

1,A,a

1,B,b

2,C,c

3,D,d

我尝试将 json 文件转换为宽 csv 文件。但是,我发现列太长,并且数据框中有多个 NA 使得 csv 文件非常大。因此我很想尝试这种方法。

我知道我可以使用tidyr 轻松地将wide 数据帧转换为long 数据帧。但是如何将一个json文件转换成long数据框呢?

【问题讨论】:

  • 这是有效的 JSON 吗?

标签: r json reshape tidyr sparklyr


【解决方案1】:

我猜你的意思是像这样的 json 对象 - 你刚刚提取了数组部分?

{
"array":[
    {"num":"1","A":"a","B":"b"},
    {"num":"2","C":"c"},
    {"num":"3","D":"d"}
 ]
}

所以一个直接的方法是:

# using rjson
library(rjson)
test <- fromJSON(file = "test.json")

# extract the "array" which is a list here though
subtest = test[[1]]

# workaround to equalize row length
max_test = max(unlist(lapply(subtest, FUN=length)))
filled_subtest = lapply(subtest, function(x){if(length(x)<max_test){y=append(x,rep(NA,max_test-length(x)));return(y)}else{return(x)}})

# create dataframe
output = data.frame(matrix(unlist(filled_subtest),nrow=length(filled_subtest), byrow=T))
colnames(output) =c("num","key","value")

【讨论】:

    【解决方案2】:

    按照 Jannes 对原始 JSON 对象的假设,这里有一个 tidyverse 方法:

    x <- '{
      "array":[
        {"num":"1","A":"a","B":"b"},
        {"num":"2","C":"c"},
        {"num":"3","D":"d"}
        ]
    }'
    
    library(jsonlite)
    library(tidyr)
    library(dplyr)
    
    fromJSON(x, simplifyDataFrame = F) %>% 
      map_depth(
        2, 
        ~as_tibble(.x) %>% 
          gather(key, value, -num)
        ) %>% 
      map(bind_rows)
    
    $`array`
    # A tibble: 4 x 3
      num   key   value
      <chr> <chr> <chr>
    1 1     A     a    
    2 1     B     b    
    3 2     C     c    
    4 3     D     d
    
    • map_depth 说拿你的清单(这里是长度为 1 的清单,与 名为“array”的单个项目)并将一个函数应用于每个嵌套 内的元素(即2 部分,而 3 将是 3 个级别 嵌套等)。
    • as_tibble 获取每个 name: value 对,并使其成为数据框的一列。
    • gather 获取除 num 之外的所有列,并将它们分配为键/值配对行(这是从“宽”数据到“长”数据的转换)。
    • 最后你 map 覆盖列表中的每个元素(同样,只有一个元素,名为“数组”)并使用 bind_rows 组合其中的每个嵌套数据框。

    这可能会根据原始对象的实际结构而有所改变。


    另一个版本:

    fromJSON(x, simplifyDataFrame = T) %>% 
      map(
        ~gather(.x, key, value, -num) %>% 
          filter(!is.na(value))
        )
    

    这会在fromJSON 级别为您完成从嵌套对象到数据框的转换。这为您提供了一个可能非常宽的数据框,其中包含很多列,因此这可能比其他方法更快或更慢,具体取决于您的数据。然后在从宽转换为长之后,过滤掉在整形期间创建的任何 NA。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多