【问题标题】:Flatten nested lists in dataframe after JSON import in R在 R 中导入 JSON 后,展平数据框中的嵌套列表
【发布时间】:2021-01-24 13:20:19
【问题描述】:

我有许多 JSON 文件,每个文件都包含许多飞行数据记录。记录类似于以下 JSON 结构。

[
    {
        "flight": {
            "operatingAirline": {
                "iataCode": "NH",
                "icaoCode": "ANA",
                "airlineDisplayCode": "NH",
                "name": "ANA All Nippon Airways"
            },
            "serviceTypeCode":"PP",
            "aircraftType": {
                "icaoCode": "B77W",
                "modelName": "B77W",
                "registration": "JA792A"
            },
            "flightNumber": {
                "airlineCode": "NH",
                "trackNumber": "00203",
                "suffix": ""
            },
            "codeShares": [
                {
                    "codeShare": {
                        "airlineCode": "LH",
                        "trackNumber": "04921",
                        "suffix": ""
                    }
                }
            ],
            "departureAirport": "HND",
            "arrivalAirport": "FRA",
            "originDate": "2016-02-23",
            "arrival": {
                "scheduled": "2016-02-23T04:20:00Z",
                "estimated": "2016-02-23T04:16:00Z",
                "actual": "2016-02-23T04:16:16Z",
                "terminal": "1",
                "gates": {
                    "gate": "B48A"
                },
                "baggageClaim": {
                    "carousel": "19"
                }
            },
            "flightStatus": ""
        }
    }
]

但执行以下操作会给我一个不完全平坦的数据框。

library(jsonlite)

df <- fromJSON(paste(getwd(), "test-data/arrival-2020-01-28-00-36.json", sep='/'), flatten=TRUE)

例如,flight.codeSharesflight.arrival.gates 列包含列表,这会阻止数据帧存储在 sqlite 文件中。我正在寻找一种解决方案来一次处理包含多条记录的 JSON 文件。

在 pyton 生态系统中,有一个 json_normalize 函数可以完成这项工作。我如何在 R 中做到这一点?

【问题讨论】:

  • 只是为了确保:您想要的是一个完全平坦的数据框,即不包含任何嵌套在单元格中的数据,而是将嵌套的数据结构分成几列?。
  • 是的,这正是我想要的。

标签: r json


【解决方案1】:

不确定是否有通用解决方案。在您的特定情况下的问题是 flight.codeShares 被解释为数据框inside 列的列表inside。 如果它只是列内的数据框,那么flatten() 可以工作。 当然,您可以通过手动扁平化codeShares 来解决这个问题,添加它 到数据框并删除原始列。

library(jsonlite)
json <- '[{
    "flight": {
      "operatingAirline": {
        "iataCode": "NH",
        "icaoCode": "ANA",
        "airlineDisplayCode": "NH",
        "name": "ANA All Nippon Airways"
      },
      "serviceTypeCode":"PP",
      "aircraftType": {
        "icaoCode": "B77W",
        "modelName": "B77W",
        "registration": "JA792A"
      },
      "flightNumber": {
        "airlineCode": "NH",
        "trackNumber": "00203",
        "suffix": ""
      },
      "codeShares": [
        {
          "codeShare": {
            "airlineCode": "LH",
            "trackNumber": "04921",
            "suffix": ""
          }
        },
        {
          "codeShare": {
            "airlineCode": "??",
            "trackNumber": "99999",
            "suffix": ""
          }
        }
      ],
      "departureAirport": "HND",
      "arrivalAirport": "FRA",
      "originDate": "2016-02-23",
      "arrival": {
        "scheduled": "2016-02-23T04:20:00Z",
        "estimated": "2016-02-23T04:16:00Z",
        "actual": "2016-02-23T04:16:16Z",
        "terminal": "1",
        "gates": {
          "gate": "B48A"
        },
        "baggageClaim": {
          "carousel": "19"
        }
      },
      "flightStatus": ""
    }
}]'
df <- fromJSON(json, flatten=TRUE, simplifyVector = TRUE)
df <- cbind(df, flatten(df$flight.codeShares[[1]]))
#> Warning in data.frame(..., check.names = FALSE): Zeilennamen wurden in einer
#> short Variablen gefunden und wurden verworfen
df$flight.codeShares <- NULL

检查结果

names(df)
#>  [1] "flight.serviceTypeCode"                    
#>  [2] "flight.departureAirport"                   
#>  [3] "flight.arrivalAirport"                     
#>  [4] "flight.originDate"                         
#>  [5] "flight.flightStatus"                       
#>  [6] "flight.operatingAirline.iataCode"          
#>  [7] "flight.operatingAirline.icaoCode"          
#>  [8] "flight.operatingAirline.airlineDisplayCode"
#>  [9] "flight.operatingAirline.name"              
#> [10] "flight.aircraftType.icaoCode"              
#> [11] "flight.aircraftType.modelName"             
#> [12] "flight.aircraftType.registration"          
#> [13] "flight.flightNumber.airlineCode"           
#> [14] "flight.flightNumber.trackNumber"           
#> [15] "flight.flightNumber.suffix"                
#> [16] "flight.arrival.scheduled"                  
#> [17] "flight.arrival.estimated"                  
#> [18] "flight.arrival.actual"                     
#> [19] "flight.arrival.terminal"                   
#> [20] "flight.arrival.gates.gate"                 
#> [21] "flight.arrival.baggageClaim.carousel"      
#> [22] "codeShare.airlineCode"                     
#> [23] "codeShare.trackNumber"                     
#> [24] "codeShare.suffix"
dim(df)
#> [1]  2 24

reprex package (v0.3.0) 于 2021-01-24 创建

【讨论】:

  • 这似乎适用于一条记录。如果我在flight.codeShares 列中有多行怎么办?
  • 我试过并相应地改变了答案。我收到一个警告和一个包含两行的数据帧。除codeshares 外,大部分数据已被复制。一般来说,它可以工作,但可能不是您所期望的。如果这不是您需要的,请更新您的问题并添加更多详细信息,
  • 谢谢,我相应地更新了我的问题。也许我不够清楚,我的错。
猜你喜欢
  • 1970-01-01
  • 2020-06-10
  • 1970-01-01
  • 2019-03-18
  • 2023-03-07
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 2016-05-07
相关资源
最近更新 更多