Rust高性能数据处理库polars-ffi的使用,polars-ffi提供高效数据分析和操作接口
Rust高性能数据处理库polars-ffi的使用,polars-ffi提供高效数据分析和操作接口
安装
在你的项目目录中运行以下Cargo命令:
cargo add polars-ffi
或者在你的Cargo.toml中添加以下行:
polars-ffi = "0.49.1"
基本信息
- 版本: 0.49.1
- 发布时间: 约1个月前
- 许可证: MIT
- 大小: 10.4 KiB
所有者
- Ritchie Vink
- Stijn
完整示例代码
以下是一个使用polars-ffi进行数据处理的完整示例:
use polars_ffi::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建一个新的数据帧
let mut df = DataFrame::default();
// 添加列
let names = Series::new("name", &["Alice", "Bob", "Charlie"]);
let ages = Series::new("age", &[25, 30, 35]);
let cities = Series::new("city", &["New York", "London", "Paris"]);
df.with_column(names)?;
df.with_column(ages)?;
df.with_column(cities)?;
// 打印数据帧
println!("原始数据帧:");
println!("{}", df);
// 过滤年龄大于30的记录
let filtered = df.filter(&df.column("age")?.gt(30))?;
println!("过滤后的数据帧:");
println!("{}", filtered);
// 计算平均年龄
let avg_age = df.column("age")?.mean()?;
println!("平均年龄: {}", avg_age);
Ok(())
}
这个示例展示了:
- 创建一个新的数据帧
- 添加多个列
- 打印数据帧内容
- 过滤数据
- 计算聚合值
polars-ffi提供了高效的数据处理接口,特别适合需要高性能数据分析的Rust应用场景。
1 回复
Rust高性能数据处理库polars-ffi使用指南
概述
polars-ffi是Polars生态系统的FFI(Foreign Function Interface)接口,允许通过C API与其他语言进行交互,同时保持Polars的高性能数据处理能力。它提供了高效的数据分析和操作接口,特别适合需要跨语言集成的场景。
主要特性
- 高性能的列式数据处理
- 惰性执行和查询优化
- 支持多种数据类型
- 内存高效
- 线程安全设计
基本使用方法
安装
在Cargo.toml中添加依赖:
[dependencies]
polars-ffi = "0.30"
基本示例
use polars_ffi::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建上下文
let ctx = unsafe { create_context() };
// 创建DataFrame
let df = unsafe {
let series1 = create_series_i32("numbers", &[1, 2, 3, 4, 5], 5);
let series2 = create_series_utf8("letters", &["a", "b", "c", "d", "e"], 5);
create_dataframe(&[series1, series2], 2)
};
// 执行操作
let result = unsafe {
let lazy_df = dataframe_to_lazy(df);
let filtered = lazy_filter(lazy_df, "numbers > 2");
collect(filtered)
};
// 打印结果
unsafe {
print_dataframe(result);
}
// 释放资源
unsafe {
free_dataframe(df);
free_dataframe(result);
free_context(ctx);
}
Ok(())
}
完整示例代码
下面是一个完整的polars-ffi使用示例,展示了从数据创建、处理到结果输出的完整流程:
use polars_ffi::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建上下文环境
let ctx = unsafe { create_context() };
if ctx.is_null() {
return Err("Failed to create context".into());
}
// 创建两个Series:一个整数列和一个字符串列
let series1 = unsafe { create_series_i32("id", &[1, 2, 3, 4, 5], 5) };
let series2 = unsafe { create_series_utf8("name", &["Alice", "Bob", "Charlie", "David", "Eve"], 5) };
// 检查Series创建是否成功
if series1.is_null() || series2.is_null() {
unsafe {
free_context(ctx);
}
return Err("Failed to create series".into());
}
// 从Series创建DataFrame
let df = unsafe { create_dataframe(&[series1, series2], 2) };
if df.is_null() {
unsafe {
free_series(series1);
free_series(series2);
free_context(ctx);
}
return Err("Failed to create DataFrame".into());
}
// 转换为惰性DataFrame以进行查询优化
let lazy_df = unsafe { dataframe_to_lazy(df) };
// 执行过滤操作:选择id大于2的记录
let filtered = unsafe { lazy_filter(lazy_df, "id > 2") };
// 添加计算列:名字长度
let with_length = unsafe {
lazy_with_column(
filtered,
"name_length",
"str_length(name)",
None
)
};
// 执行查询并收集结果
let result = unsafe { collect(with_length) };
// 打印结果DataFrame
unsafe {
print_dataframe(result);
}
// 释放所有分配的资源
unsafe {
free_dataframe(df);
free_dataframe(result);
free_context(ctx);
}
Ok(())
}
高级功能
1. 数据聚合
unsafe {
let lazy_df = dataframe_to_lazy(df);
let aggregated = lazy_groupby(
lazy_df,
&["letters"],
&[("numbers", "sum")],
GroupByOptions::default()
);
let result = collect(aggregated);
print_dataframe(result);
free_dataframe(result);
}
2. 数据连接
unsafe {
let df1 = create_sample_dataframe_1();
let df2 = create_sample_dataframe_2();
let joined = join_dataframes(
df1,
df2,
"id",
"id",
JoinType::Inner,
JoinOptions::default()
);
print_dataframe(joined);
free_dataframe(joined);
}
3. 自定义函数应用
unsafe {
let lazy_df = dataframe_to_lazy(df);
let with_custom = lazy_with_column(
lazy_df,
"squared",
"numbers * numbers",
None
);
let result = collect(with_custom);
print_dataframe(result);
free_dataframe(result);
}
性能提示
- 尽可能使用惰性评估(Lazy API)来构建整个查询计划,最后再执行
collect
- 批量操作比逐行操作更高效
- 合理使用数据类型,避免不必要的类型转换
- 复用DataFrame和Context对象,减少创建开销
内存管理注意事项
由于polars-ffi使用C API,需要手动管理内存:
- 每个
create_
函数创建的对象都需要对应的free_
函数释放 - 操作完成后及时释放不再需要的对象
- 在多线程环境中确保正确的内存访问顺序
错误处理
所有FFI函数都可能返回错误,实际使用时应检查返回状态:
unsafe {
let result = create_series_i32("data", &[1, 2, 3], 3);
if result.is_null() {
let error = get_last_error();
eprintln!("Error creating series: {}", error);
free_error_message(error);
return Err("Failed to create series".into());
}
// 正常处理...
}
polars-ffi为Rust程序提供了高性能数据处理能力,同时保持了与其他语言交互的可能性,是构建数据密集型应用的强大工具。