Sam*_*Sam 6 struct dataframe rust rust-polars
假设我有一个像这样的结构向量:
struct Test {
id:u32,
amount:u32
}
fn main() {
let test_vec:Vec<Test> = vec![Test{id:1,amount:3}, Test{id:3,amount:4}];
}
Run Code Online (Sandbox Code Playgroud)
有没有办法将其放入极坐标数据框中,其中列名称是结构字段?
希望得到如下输出:
id amount
0 1 3
1 3 4
Run Code Online (Sandbox Code Playgroud)
经过一番努力后,我找到了以下解决方案。
如果您有自定义结构的向量,要将其放入 Polars 数据帧中,您可以执行以下操作:
// 1. Derive serde::Serialize for your struct
#[derive(Serialize)]
struct Test {
id:u32,
amount:u32
}
// (Adding new method here for quality of life).
impl Test {
fn new(id:u32, amount:u32) -> Self{
Test{id,amount}
}
}
// 2. Jsonify your struct Vec
let test_vec:Vec<Test> = vec![Test::new(1,3), Test::new(3,4)];
let json = serde_json::to_string(&test_vec).unwrap();
// 3. Create cursor from json
let cursor = Cursor::new(json);
// 4. Create polars DataFrame from reading cursor as json
let df = JsonReader::new(cursor)
.finish()
.unwrap();
Run Code Online (Sandbox Code Playgroud)
我不喜欢接受的答案有几个原因
chrono::NaiveDate
字段,您会丢失类型信息 - 它将作为 a 返回str
到您的DataFrame
.我认为更好的解决方案是宏:
macro_rules! struct_to_dataframe {
($input:expr, [$($field:ident),+]) => {
{
// Extract the field values into separate vectors
$(let mut $field = Vec::new();)*
for e in $input.into_iter() {
$($field.push(e.$field);)*
}
df! {
$(stringify!($field) => $field,)*
}
}
};
}
Run Code Online (Sandbox Code Playgroud)
您应该能够像这样调用它:
struct Test {
id:u32,
amount:u32
}
impl Test {
fn new(id:u32, amount:u32) -> Self{
Test{id,amount}
}
}
let test_vec:Vec<Test> = vec![Test::new(1,3), Test::new(3,4)];
let df = struct_to_dataframe!(test_vec, [id, amount]).unwrap();
Run Code Online (Sandbox Code Playgroud)