如何快速解码熊猫数据帧转储的json

Posted

技术标签:

【中文标题】如何快速解码熊猫数据帧转储的json【英文标题】:How to decode a json dumped by pandas dataframe in swift 【发布时间】:2022-01-11 08:23:53 【问题描述】:

我有一个 json 数据,它由 rest api 以

的形式返回

‘split’ : dict like ‘index’ -> [index], ‘columns’ -> [columns], ‘data’ -> [values] 这是在 Python 中使用 pandas.to_json(orient=‘split’) 生成的

我想把它解码成一个 swift 对象。我尝试使用 decodedable 但我不知道如何将列位置动态分配给对象

示例数据:


"columns":
   ["cprcode","iprcode","psqty"],
"index":
   [0,3,4,5,6,11],
"data":
   [
     [123,"abc",123],
     [424, "ads",145],
     [63, "hrw",475],
     [8685, "gds",848],
     [754, "ah",659],
     [374, "rh",597],
   ]

我希望输出在 [Product] 的 for 中 在哪里

struct Product
  let cprcode: Int
  let iprcode: String
  let psqty: Int

我试过了

使用这样的自定义数组类进行解码,但我不确定如何将它们拆分为产品对象。请注意,列是动态的,因此对数据中的列顺序进行硬编码是有风险的。

class ProductDF:Codable
    let columns:[String]
    let index:[Int]
    let data:[[Product]]

【问题讨论】:

我认为您希望在struct Product 中根据 API 的输出拥有动态 var 名称可能是不可能的。您可以尝试将 Product 作为字典,如 column:value 以映射到动态数据。如果您在实现这一点时遇到困难,我可以发布示例代码。 请提供样品。我知道 var 名称,但无法保证顺序。 【参考方案1】:

这可以通过自定义init(from:) 来完成,我们使用嵌套容器从“数据”中提取产品对象。

由于“数据”下的每个子数组都是一个产品,我们稍微更改声明

struct ProductDF: Codable 
    let columns: [String]
    let index: [Int]
    let data: [Product]

为了稍微简化代码,我们为列创建了一个枚举

enum DataColumn: String 
    case cprcode, iprcode, psqty

然后是我们添加到ProductDFinit(from:)

init(from decoder: Decoder) throws 
    let container = try decoder.container(keyedBy: CodingKeys.self)
    columns = try container.decode([String].self, forKey: .columns)
    index = try container.decode([Int].self, forKey: .index)

    var dataContainer = try container.nestedUnkeyedContainer(forKey: .data)
    var products = [Product]()
    while !dataContainer.isAtEnd 
        var array = try dataContainer.nestedUnkeyedContainer()
        var cprCode = 0
        var iprCode = ""
        var psQty = 0
        for column in columns 
            switch DataColumn(rawValue: column) 
            case .cprcode:
                cprCode = try array.decode(Int.self)
            case .iprcode:
                iprCode = try array.decode(String.self)
            case .psqty:
                psQty = try array.decode(Int.self)
            case .none:
                fatalError()
            
        
        let product = Product(cprcode: cprCode, iprcode: iprCode, psqty: psQty)
        products.append(product)
    
    data = products

这应该可以完成基本工作,尽管我建议通过抛出错误而不是使用 fatalError 来改进错误处理,并检查是否已将某些内容分配给 while 循环内的所有 3 个变量,例如通过使它们可选并在创建 Product 之前验证所有都不为零。

【讨论】:

以上是关于如何快速解码熊猫数据帧转储的json的主要内容,如果未能解决你的问题,请参考以下文章

解码 m4a 并转储 PCM 数据会返回噪声

如何以漂亮的打印风格在 JSON 中编写数据框?

将帧缓冲区转储转换为图像(bmp、png 等)

如何将字典转储到 JSON 文件?

如何在不使用转储的情况下在 python 中编写 json 文件

PHP:如何从字符串转储中提取 JSON 字符串