【问题标题】:Unpack json columns into a dataframe将 json 列解压缩到数据框中
【发布时间】:2021-02-08 02:56:09
【问题描述】:

我在数据框列中有 json 字符串。我想将所有这些新的 json 列带入数据框中。

# Input
JsonID <- as.factor(c(1,2,3))
JsonString1 = "{\"device\":{\"site\":\"Location1\"},\"tags\":{\"Engine Pressure\":\"150\",\"timestamp\":\"2608411982\",\"historic\":false,\"adhoc\":false},\"online\":true,\"time\":\"2608411982\"}"
JsonString2 = "{\"device\":{\"site\":\"Location2\"},\"tags\":{\"Engine Pressure\":\"160\",\"timestamp\":\"3608411983\",\"historic\":false,\"adhoc\":false},\"online\":true,\"time\":\"3608411983\"}"
JsonString3 = "{\"device\":{\"site\":\"Location3\"},\"tags\":{\"Brake Fluid\":\"100\",\"timestamp\":\"4608411984\",\"historic\":false,\"adhoc\":false},\"online\":true,\"time\":\"4608411984\"}"
JsonStrings = c(JsonString1, JsonString2, JsonString3)
Example <- data.frame(JsonID, JsonStrings)

使用 jsonlite 库,我可以将每个 json 字符串变成一个 1 行数据框。

library(jsonlite)

# One row dataframes
DF1 <- data.frame(fromJSON(JsonString1))
DF2 <- data.frame(fromJSON(JsonString2))
DF3 <- data.frame(fromJSON(JsonString3))

不幸的是,JsonID 变量列丢失了。所有 json 字符串共享共同的列名,例如“时间”。但是有些列名他们不共享。通过将数据旋转更长的时间,我可以将所有数据帧 Rbind 在一起。

library(dplyr)
library(tidyr)

# Row bindable one row dataframes
DF1_RowBindable <- DF1 %>%
  rename_all(~gsub("tags.", "", .x)) %>% 
  tidyr::pivot_longer(cols = c(colnames(.)[2]))

有没有更好的方法来做到这一点?

我以前从未使用过 json 字符串。解决方案必须在计算上具有可扩展性。

【问题讨论】:

    标签: r json dplyr wrangle


    【解决方案1】:

    我们可以将来自fromJSON 的数据存储在数据框本身的列表中,这样我们就不会丢失数据中已有的任何信息。我们可以使用unnest_wider 从命名列表中创建新列。

    library(dplyr)
    library(tidyr)
    library(jsonlite)
    
    Example %>%
      rowwise() %>%
      mutate(data = list(fromJSON(JsonStrings))) %>%
      unnest_wider(data) %>%
      select(-JsonStrings) %>%
      unnest_wider(tags) %>%
      unnest_wider(device)
    
    # JsonID site      `Engine Pressure` timestamp  historic adhoc `Brake Fluid` online time      
    #  <fct>  <chr>     <chr>             <chr>      <lgl>    <lgl> <chr>         <lgl>  <chr>     
    #1 1      Location1 150               2608411982 FALSE    FALSE NA            TRUE   2608411982
    #2 2      Location2 160               3608411983 FALSE    FALSE NA            TRUE   3608411983
    #3 3      Location3 NA                4608411984 FALSE    FALSE 100           TRUE   4608411984
    

    由于每一列(datatagsdevice)的长度不同,我们需要在每一列上分别使用unnest_wider

    【讨论】:

    • Azure 数据块在 rowwise() 上出现错误。我们如何使用 spark/sparklyr 工具执行相同的操作。同时避免将数据带入databricks节点,这会耗尽内存。
    • 很遗憾,我没有任何使用 spark 的经验,所以我不知道如何翻译。也许你可以提出一个新问题来解决这个问题。
    • 是否有一种方法可以使用 dplyrs transmute() 获得相同的结果,同时避免 rowwise()。这将是 Spark 友好的。
    • 这是一个使用 transmute 的小例子。单独的未嵌套列是手动命名的。不幸的是,我无法手动命名所有未嵌套的列。 therinspark.com/data.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 2013-06-13
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2019-04-12
    相关资源
    最近更新 更多