我想知道如何将JSON文件读入Rust中的polars DataFrame中的"data"键.但是,我相信我所拥有的JSON文件的 struct 很难实现.

以下是JSON文件的第一个 struct ,其中包含数据类型.

{
  "data": [
    {
      "dataItemName": "TICKER",
      "result": [
        "AAPL",
        "MSFT",
        "TSLA"
      ],
      "dataType": "STRING",
      "error": 0
    },
    {
      "dataItemName": "SALES",
      "result": [ 
        259968,
        143015,
        24578
      ],
      "dataType": "DOUBLE",
      "error": 0
    },
    {
      "dataItemName": "CNAME",
      "result": [
        "Apple Inc.",
        "Microsoft Corporation",
        "Tesla Inc"
      ],
      "dataType": "STRING",
      "error": 0
    },
    {
      "dataItemName": "PRICE",
      "result": [
        115.98,
        214.22,
        430.83
      ],
      "dataType": "DOUBLE",
      "error": 0
    },
    {
      "dataItemName": "ASSETS",
      "result": [
        338516,
        301311,
        34309
      ],
      "dataType": "DOUBLE",
      "error": 0
    }
  ]
}

这是我在Rust中try 的.

use polars::prelude::*;


fn main() {
    let json_file = std::fs::File::open("data/test_merged.json").unwrap();
    let df = JsonReader::new(json_file).finish().unwrap();
    println!("{:?}", df);
}

下面是Rust输出的例子,

shape: (1, 1)
┌───────────────────────────────────┐
│ data                              │
│ ---                               │
│ list[struct[63]]                  │
╞═══════════════════════════════════╡
│ [{0.0,0.530558,3.38631,"2023-06-… │
└───────────────────────────────────┘

只有3种数据类型,即Stings Floats和Integers.

这里有一个类似的问题,适用于Python版本. transform json to polars dataframe

推荐答案

如果性能很重要,那么@BallpointBen的版本不是你能得到的最快的版本;这里有一个更高性能的版本:

pub fn convert(json: &str) -> Result<DataFrame, Box<dyn Error>> {
    use serde::Deserialize;

    #[derive(Debug, Deserialize)]
    #[serde(untagged)]
    enum Values {
        String(Vec<String>),
        Double(Vec<f64>),
    }

    #[derive(Debug, Deserialize)]
    #[serde(rename_all = "UPPERCASE")]
    enum DataType {
        String,
        Double,
    }

    #[derive(Debug, Deserialize)]
    #[serde(rename_all = "camelCase")]
    struct Column {
        data_item_name: String,
        result: Values,
        data_type: DataType,
    }

    #[derive(Debug, Deserialize)]
    struct Data {
        data: Vec<Column>,
    }

    let data = serde_json::from_str::<Data>(json)?;
    let df = data
        .data
        .into_iter()
        .map(|column| match column.data_type {
            DataType::String => {
                let Values::String(values) = column.result else {
                    return Err("column type mismatch");
                };
                Ok(Series::new(&column.data_item_name, values))
            }
            DataType::Double => {
                let Values::Double(values) = column.result else {
                    return Err("column type mismatch");
                };
                Ok(Series::from_vec(&column.data_item_name, values))
            }
        })
        .collect::<Result<DataFrame, _>>()?;

    Ok(df)
}

包含1,000个随机条目的基准:

BallpointBen            time:   [338.41 µs 340.05 µs 341.85 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

Mine                    time:   [195.82 µs 196.79 µs 197.95 µs]
Found 11 outliers among 100 measurements (11.00%)
  8 (8.00%) high mild
  3 (3.00%) high severe

Rust相关问答推荐

trait声明中的生命周期参数

如何使用Match比较 struct 中的值

Box::new()会从一个堆栈复制到另一个堆吗?

有没有办法在Rust中配置常量变量的值?

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

如何在函数中返回自定义字符串引用?

获取与父字符串相关的&;str的原始片段

如何创建一个可变的嵌套迭代器?

为什么`str`类型可以是任意大小(未知大小),而`string`类型的大小应该是已知的?

为什么rustc会自动降级其版本?

确保参数是编译时定义的字符串文字

borrow 是由于对 `std::sync::Mutex>` 的解引用强制而发生的

信号量释放后 Rust 输出挂起线程

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

Rust 并行获取对 ndarray 的每个元素的可变引用

如何将 &[T] 或 Vec<T> 转换为 Arc<Mutex<[T]>>?

为什么 for_each 在释放模式(cargo run -r)下比 for 循环快得多?

如何使返回 XMLError 的方法与 anyhow::Error 兼容?

使用方法、关联函数和自由函数在 Rust 中初始化函数指针之间的区别

有没有办法在 Rust 中对 BigInt 进行正确的位移?