Polars.NET.Core
0.6.0
dotnet add package Polars.NET.Core --version 0.6.0
NuGet\Install-Package Polars.NET.Core -Version 0.6.0
<PackageReference Include="Polars.NET.Core" Version="0.6.0" />
<PackageVersion Include="Polars.NET.Core" Version="0.6.0" />
<PackageReference Include="Polars.NET.Core" />
paket add Polars.NET.Core --version 0.6.0
#r "nuget: Polars.NET.Core, 0.6.0"
#:package Polars.NET.Core@0.6.0
#addin nuget:?package=Polars.NET.Core&version=0.6.0
#tool nuget:?package=Polars.NET.Core&version=0.6.0
Polars.NET
F# & C# E2E examples repo:Polars.NET-Cookbook
High-Performance, DataFrame Engine for .NET, powered by Rust Polars & Apache Arrow. With cloud and deltalake features.
Supported Platforms: Windows (x64), Linux (x64/ARM64, glibc/musl), macOS (ARM64). Cloud: AWS, Azure and GCP Data Lake: Delta Lake
<p style="font-size:1.3em; font-weight:bold; background-color:#ffff99;"> 99% API in python Polars now is available in both Polars.NET and Polars.FSharp.<br/> </p>
Why Polars.NET exists
This is the game I'd like to play: binding the lightning-fast Polars engine to the .NET ecosystem. And it brings a lot of fun.
Polars.NET vs Python Ecosystem
<picture> <source media="(prefers-color-scheme: dark)" srcset="assets/benchmark_python_dark.png"> <img alt="Polars.NET vs Python" src="assets/benchmark_python_light.png"> </picture>
Speedup vs Legacy .NET
<picture> <source media="(prefers-color-scheme: dark)" srcset="assets/benchmark_summary_dark.png"> <img alt="Speedup Summary" src="assets/benchmark_summary_light.png"> </picture>
Delta Lake Read
Delta Lake Write
Installation
C# Users:
dotnet add package Polars.NET
# And then add the native runtime for your current environment:
dotnet add package Polars.NET.Native.win-x64
# Add LINQ extension package once you need to write LINQ
dotnet add package Polars.NET.Linq
# Add ML.NET integration if needed
dotnet add package Polars.NET.ML
F# Users:
dotnet add package Polars.FSharp
# And then add the native runtime for your current environment:
dotnet add package Polars.NET.Native.win-x64
# Add LINQ extension package once you need to write LINQ or computation expressions
dotnet add package Polars.NET.Linq
# Add ML.NET integration if needed
dotnet add package Polars.NET.ML
- Requirements: .NET 8+.
- Hardware: CPU with AVX2 support (x86-64-v3). Roughly Intel Haswell (2013+) or AMD Excavator (2015+). If you have AVX-512 supported CPU, please try to compile Rust core on your machine use RUSTFLAGS='-C target-cpu=native'
Built Specially for .NET
Bringing .NET to Polars is not enough, it is the time to bring Polars to .NET.
- ML.NET & Tensor Interop
Prepare data with polars, then train it with ML.NET & ONNX, finally analyze results back with polars.
Notice: Tensor Interop doesn't need any extra package but ML.NET integration requires Polars.NET.ML extension nuget package.
// ==========================================
// Data Loading
// ==========================================
var hfUrl = "https://huggingface.co/datasets/scikit-learn/iris/resolve/refs%2Fconvert%2Fparquet/default/train/0000.parquet";
var options = CloudOptions.Http(new Dictionary<string, string>
{
{ "User-Agent", "Polars.NET-Test" }
});
using var lf = LazyFrame.ScanParquet(hfUrl, cloudOptions: options);
// sepal length (cm), sepal width (cm), petal length (cm), petal width (cm)
using var cleanlf = lf.Cast((typeof(double),typeof(float)));
using var cleanDf = cleanlf.WithColumns(Pl.ConcatArray(Cs.Float().ToExpr().Alias("Features"))).Collect();
// ==========================================
// Polars -> ML.NET
// ==========================================
var dataView = cleanDf.AsDataView();
var mlContext = new MLContext(seed: 42);
// ==========================================
// ML.NET Pipeline
// ==========================================
// Form VBuffer<float> tensor
var pipeline = mlContext.Clustering.Trainers.KMeans("Features", numberOfClusters: 3);
var model = pipeline.Fit(dataView);
// ==========================================
// ML.NET Transform and Read Back
// ==========================================
var predictions = model.Transform(dataView);
// ML.NET -> Polars
using var resultDf = predictions.ToDataFrame();
// ==========================================
// TensorInterop
// ==========================================
float[,] matrix = new float[,]
{
{ 1.1f, 1.2f, 1.3f },
{ 2.1f, 2.2f, 2.3f }
};
using var series = Series.From("ffi_matrix", matrix);
var (ptr, shape) = series.AsDangerousUnmanagedTensor<float>();
int totalElements = (int)(shape[0] * shape[1]);
float* rawFloatPtr = (float*)ptr.ToPointer();
var nativeSpan = new ReadOnlySpan<float>(rawFloatPtr, totalElements);
- ADO.NET
Polars.NET DataReader is generic typed without boxing/unboxing on hot path.
// To DataReader
using var bulkReader = df.AsDataReader(bufferSize: 100, typeOverrides: overrides);
// From DataReader
using var sourceReader = sourceTable.CreateDataReader();
var df = DataFrame.ReadDatabase(sourceReader);
- C# LINQ & F# Computation Expression
With Polars.NET.Linq Extension package(Thanks to Linq2DB), playing DataFrame/Series with LINQ/Query block is available now.
using var dfDepts = DataFrame.From(depts);
using var dfEmps = DataFrame.From(emps);
using var db = new PolarsDataContext(new SqlContext(), ownsContext: true);
var deptQuery = dfDepts.AsQueryable<DeptDto>(db);
var empQuery = empQuery.AsQueryable<EmpDto>(db);
var query = deptQuery
.LeftJoin(
empQuery,
d => d.DeptId,
e => e.DeptId,
(d, e) => new
{
d.DeptId,
d.DeptName,
EmployeeName = e != null ? e.Name : "NO_EMPLOYEE"
})
.OrderBy(x => x.DeptId)
.ThenBy(x => x.EmployeeName)
.Select(x => new JoinResult
{
DeptName = x.DeptName,
EmployeeName = x.EmployeeName
});
var results = query.ToList();
let queryResult =
query {
for d in deptQuery do
leftOuterJoin e in empQuery on (d.DeptId = e.DeptId) into empGroup
for e in empGroup.DefaultIfEmpty() do
sortBy d.DeptId
thenBy e.Name
select {|
DeptName = d.DeptName
EmployeeName = if box e = null then "NO_EMPLOYEE" else e.Name
|}
}
|> Seq.toList
Quick Start
C# Example
using Polars.CSharp;
using Pl = Polars.CSharp.Polars;
// 1. Create a DataFrame
var data = new[] {
new { Name = "Alice", Age = 25, Dept = "IT" },
new { Name = "Bob", Age = 30, Dept = "HR" },
new { Name = "Charlie", Age = 35, Dept = "IT" }
};
var df = DataFrame.From(data);
// 2. Filter & Aggregate
var res = df
.Filter(Pl.Col("Age") > 28)
.GroupBy("Dept")
.Agg(
Pl.Col("Age").Mean().Alias("AvgAge"),
Pl.Col("Name").Count().Alias("Count")
)
.Sort("AvgAge", descending: true);
// 3. Output
res.Show();
// shape: (2, 3)
// ┌──────┬────────┬───────┐
// │ Dept ┆ AvgAge ┆ Count │
// │ --- ┆ --- ┆ --- │
// │ str ┆ f64 ┆ u32 │
// ╞══════╪════════╪═══════╡
// │ IT ┆ 35.0 ┆ 1 │
// │ HR ┆ 30.0 ┆ 1 │
// └──────┴────────┴───────┘
F# Example
open Polars.FSharp
// 1. Scan CSV (Lazy)
let lf = LazyFrame.ScanCsv "users.csv"
// 2. Transform Pipeline
let res =
lf
|> pl.filterLazy (pl.col "age" .> pl.lit 28)
|> pl.groupByLazy [ pl.col "dept" ]
|> pl.aggLazy
[
pl.col("age").Mean().Alias "AvgAge"
pl.col("name").Count().Alias "Count"
]
|> pl.sortAscendingLazy [pl.col "AvgAge"]
|> pl.collect
|> pl.show
Benchmark
Extension Nuget Package
- Polars.NET.Linq
- Polars.NET.ML
Architecture
3-Layer Architecture ensures API stability.
- Hand-written Rust C ABI layer bridging .NET and Polars. (native_shim)
- .NET Core layer for dirty works like unsafe ops, wrappers, LibraryImports. (Polars.NET.Core)
- High level C# and F# API layer here. No unsafe blocks. (Polars.CSharp & Polars.FSharp)
Roadmap
More code examples, user cases
Native LINQ Provider
Contributing
Contributions are welcome. Whether it's adding new expression mappings, improving documentation, or optimizing the FFI layer.
Fork the repo.
Create your feature branch.
Submit a Pull Request.
License
MIT License. See LICENSE for details. For Third party licenses please check THIRD_PARTY_LICENSES.html
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Apache.Arrow (>= 23.0.0)
- Apache.Arrow.Adbc (>= 0.23.0)
- FSharp.Core (>= 10.0.100)
- System.Numerics.Tensors (>= 10.0.5)
-
net8.0
- Apache.Arrow (>= 23.0.0)
- Apache.Arrow.Adbc (>= 0.23.0)
- FSharp.Core (>= 8.0.100)
- System.Numerics.Tensors (>= 10.0.5)
-
net9.0
- Apache.Arrow (>= 23.0.0)
- Apache.Arrow.Adbc (>= 0.23.0)
- FSharp.Core (>= 9.0.100)
- System.Numerics.Tensors (>= 10.0.5)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Polars.NET.Core:
| Package | Downloads |
|---|---|
|
Polars.NET
A blazing fast DataFrame library for .NET, powered by the Rust Polars engine and Apache Arrow. Features multi-threaded query execution, lazy evaluation, and data extraction into modern .NET Tensors (ReadOnlyTensorSpan) for hardware-accelerated SIMD math and AI inference. |
|
|
Polars.FSharp
Idiomatic F# API for Polars DataFrame library with strict type safety and pipeline support. |
|
|
Polars.NET.Linq
LINQ Translation Engine for Polars.NET and Polars.FSharp. Write strong-typed C#/F# queries and execute them at native speed |
|
|
Polars.NET.ML
The Machine Learning extension for Polars.NET. This package provides high-speed data bridges between Polars DataFrames, Apache Arrow memory, ML.NET (IDataView). Unlock hardware-accelerated SIMD math, train classic ML models, and seamlessly integrate with deep learning pipelines (ONNX). |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.6.0 | 144 | 6/9/2026 |
| 0.5.0 | 184 | 5/26/2026 |
| 0.4.0 | 2,228 | 3/20/2026 |
| 0.3.1 | 261 | 2/28/2026 |
| 0.3.0 | 348 | 2/26/2026 |
| 0.2.1-beta1 | 488 | 2/6/2026 |
| 0.2.0-beta1 | 214 | 2/4/2026 |
| 0.1.0-beta1 | 149 | 1/14/2026 |
| 0.1.0-alpha2 | 136 | 1/10/2026 |
| 0.1.0-alpha1 | 146 | 1/4/2026 |