Создайте фрейм данных Polars с плоским файлом Json

Проблема, с которой я столкнулся, заключается в попытке прочитать сглаженный файл JSON в фрейм данных Polars в Rust.

Вот пример Json с плоским форматом JSON. Как эта структура будет считана в DataFrame без маркировки dtype каждого столбца в структуре?

{
  "data": [
    {
      "requestId": "IBM",
      "date": "2024-03-19",
      "sales": 61860,
      "company": "International Business Machines",
      "price": 193.34,
      "score": 7
    },
    {
      "requestId": "AAPL",
      "date": "2024-03-19",
      "sales": 383285,
      "company": "Apple Inc.",
      "price": 176.08,
      "score": 9
    },
    {
      "requestId": "MSFT",
      "date": "2024-03-19",
      "sales": 211915,
      "company": "Microsoft Corporation",
      "price": 421.41,
      "score": 7
    } 
  ]
}

В данных есть только целые числа, числа с плавающей запятой и строки.

Вот пример структуры, которую я пытался создать. Если меняются более 200 столбцов, было бы лучше создать HashMap для динамического хранения столбцов?

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Row {
    requestId: String,
    date: String,
    #[serde(flatten)]
    company_data: HashMap<String, serde_json::Value>,
}

Это второй вопрос для не сглаженных данных JSON: Преобразуйте ключ JSON в фрейм данных Polars

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
0
165
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этот формат почти соответствует ожиданиям Polars JsonReader; проблема заключается только в объекте верхнего уровня. Однако мы можем удалить его с помощью манипуляций со строками:

pub fn flattened(json: &str) -> Result<DataFrame, Box<dyn Error>> {
    let json = json.trim();
    let json = json
        .strip_prefix("{")
        .ok_or("invalid JSON")?
        .strip_suffix("}")
        .ok_or("invalid JSON")?;
    let json = json.trim_start();
    let json = json.strip_prefix(r#""data""#).ok_or("invalid JSON")?;
    let json = json.trim_start();
    let json = json.strip_prefix(":").ok_or("invalid JSON")?;

    let json_reader = JsonReader::new(std::io::Cursor::new(json));
    let mut df = json_reader.finish()?;
    let date = df.column("date")?.cast(&DataType::Date)?;
    df.replace("date", date)?;

    Ok(df)
}

Еще раз спасибо за пример. Знаете ли вы, есть ли способ избежать объявления каждого поля? Например, эти данные намного больше и содержат более 200 полей. Объявление заняло бы много времени, особенно когда поля меняются. Я пытался посмотреть, можем ли мы использовать requestId и дату в качестве фиксированной ссылки, по которой выравниваются остальные поля. По сути, это мути-индекс с датой и идентификатором запроса.

Trevor Seibert 25.03.2024 23:16

@TrevorSeibert Да, схему можно опустить, и JsonReader угадает ее. Обновил ответ.

Chayim Friedman 26.03.2024 13:32

Другие вопросы по теме