Polars.NET
1.0.1
dotnet add package Polars.NET --version 1.0.1
NuGet\Install-Package Polars.NET -Version 1.0.1
<PackageReference Include="Polars.NET" Version="1.0.1" />
<PackageVersion Include="Polars.NET" Version="1.0.1" />
<PackageReference Include="Polars.NET" />
paket add Polars.NET --version 1.0.1
#r "nuget: Polars.NET, 1.0.1"
#:package Polars.NET@1.0.1
#addin nuget:?package=Polars.NET&version=1.0.1
#tool nuget:?package=Polars.NET&version=1.0.1
<div align="center"> <img src="assets/logo.svg" width="120" height="120" alt="Polars.NET Logo" /> <h1>Polars.NET</h1> <p><b>Blazingly Fast DataFrames & LINQ Engine for .NET</b></p> <p><i>Powered by Rust Polars & Apache Arrow</i></p>
<p> <a href="https://www.nuget.org/packages/Polars.NET"><img src="https://img.shields.io/nuget/v/Polars.NET.svg" alt="NuGet Polars.NET" /></a> <a href="https://www.nuget.org/packages/Polars.NET"><img src="https://img.shields.io/nuget/dt/Polars.NET.svg" alt="NuGet Downloads" /></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License" /></a> <a href="https://errorlsc.github.io/Polars.NET/"><img src="https://img.shields.io/badge/docs-online-512BD4.svg?style=flat-square&logo=read-the-docs&logoColor=white" alt="Documentation" /></a> <a href="https://github.com/sponsors/ErrorLSC"><img src="https://img.shields.io/badge/Sponsor-GitHub-ea4aaa.svg?style=flat-square&logo=githubsponsors&logoColor=white" alt="Sponsor" /></a> </p>
<p> <a href="https://errorlsc.github.io/Polars.NET/"><b>Documentation Website</b></a> | <a href="https://errorlsc.github.io/Polars.NET/articles/quickstart"><b>Quick Start</b></a> | <a href="https://errorlsc.github.io/Polars.NET/articles/linq"><b>LINQ Guide</b></a> | <a href="https://errorlsc.github.io/Polars.NET/api/csharp_generated/DataFrame"><b>C# API</b></a> | <a href="https://errorlsc.github.io/Polars.NET/api/fsharp_generated/pl"><b>F# API</b></a> | <a href="https://errorlsc.github.io/Polars.NET/llms.txt"><b>llms.txt</b></a> | <a href="https://github.com/ErrorLSC/Polars.NET-Cookbook"><b>Cookbook</b></a> </p>
<br /> <img src="assets/comic.jpg" alt="Polars.NET: Rust Polars + .NET LINQ" width="800" /> </div>
I really dreamed that we can play with DataFrames in .NET just like python, now we got a much more enjoyable and funny one.
Highlights
- Native Pushdown LINQ: Compiles C# LINQ and F# query { } directly into Rust Polars physical plans then be optimized & executed natively. Verified with all 22 TPC-H benchmark queries implemented in native LINQ without client-side fallback. Includes .Explain(), .ToDataFrame(), and joins between in-memory collections and DataFrames.
- High Performance: Built on the Rust Polars engine and Apache Arrow columnar memory format. Delivers vectorized SIMD execution, query optimization (predicate and projection pushdown, common subplan elimination), and out-of-core streaming execution for larger-than-memory datasets.
- Deep .NET Ecosystem Integration: First-class bridges to standard .NET abstractions, including
IAsyncEnumerable<T>streaming, ADO.NETIDataReader/DbDataReaderingestion, ML.NETIDataViewpipelines, and direct extraction intoSystem.Numerics.Tensors(ReadOnlyTensorSpan) for numerical computing and model inference. - Universal I/O & Storage: Reads and writes Parquet, CSV, JSON/NDJSON, Arrow IPC, Excel, and Avro. Native integration with Arrow Database Connectivity (ADBC) and Delta Lake (ACID transactions, time travel, and SQL MERGE), targeting both local filesystems and cloud object storage (Amazon S3, Azure Blob, Google Cloud Storage).
Installation
Polars.NET targets .NET 8.0 and requires referencing both the managed API package and the matching native runtime package for your execution platform:
C# Users
# C# API package
dotnet add package Polars.NET
# Platform native runtime (choose matching your deployment target):
dotnet add package Polars.NET.Native.win-x64
# dotnet add package Polars.NET.Native.linux-x64
# dotnet add package Polars.NET.Native.linux-arm64
# dotnet add package Polars.NET.Native.osx-arm64
# Optional: ML.NET integration
dotnet add package Polars.NET.ML
F# Users
# F# API package
dotnet add package Polars.FSharp
# Platform native runtime:
dotnet add package Polars.NET.Native.win-x64
Quick Tour
1. C# LINQ Query
Write standard C# LINQ queries then execute them natively without intermediate managed objects:
using Polars.CSharp;
using Polars.CSharp.Linq;
public record Order(int Id, string Customer, string Region, double Revenue);
List<Order> orders = GetOrders();
// 1. Direct entry from in-memory collection, DataFrame, or ADO.NET IDataReader:
var query = from o in orders.AsPolarsQueryable()
where o.Revenue >= 500.0 && o.Region != "Test"
group o by o.Region into g
select new {
Region = g.Key,
TotalRevenue = g.Sum(x => x.Revenue),
OrderCount = g.Count()
};
// 2. Materialize directly into a Polars DataFrame:
using DataFrame resultDf = query.ToDataFrame();
resultDf.Show();
// 3. Or inspect the execution plan:
query.InspectPlan();
2. C# Fluent API
Polars DSL for complex analytics, column expressions, and Selectors:
using Polars.CSharp;
using Pl = Polars.CSharp.Polars;
using Cs = Polars.CSharp.Polars.Selectors;
// Read Parquet lazily:
using var lf = LazyFrame.ScanParquet("orders/*.parquet");
using var summaryDf = lf
.Filter(Pl.Col("order_date") >= new DateOnly(2025, 1, 1))
.GroupBy("region")
.Agg(
Pl.Col("revenue").Sum().Alias("total_revenue"),
Pl.Col("customer_id").NUnique().Alias("unique_customers"),
Cs.Numeric().Mean().Name.Prefix("avg_")
)
.Sort("total_revenue", descending: true)
.Collect();
summaryDf.Show();
3. F# Query Computation Expression
F# strong typing CE, anonymous records, and pipeline combinators over native queries:
open Polars.FSharp
open Polars.FSharp.Query
// F# query { } compiles into polars execution plan:
let summaryQuery =
query {
for o in df.AsQueryable<Order>() do
where (o.Revenue >= 500.0 && o.Region <> "Test")
groupValBy o o.Region into g
select {|
Region = g.Key
TotalRevenue = g.Sum(fun x -> x.Revenue)
OrderCount = g.Count()
|}
}
use resultDf = summaryQuery.ToDataFrame()
resultDf |> DataFrame.show
4. Polars.NET Exclusive: Strongly-Typed SQL Merge
Perform ANSI SQL MERGE upsert operations directly on DataFrames or in-memory collections:
List<ProductItem> inMemoryTarget = GetTargetProducts();
List<ProductItem> incomingUpdates = GetSourceProducts();
// Start merge from a List<T>:
using DataFrame mergedDf = inMemoryTarget.Merge(incomingUpdates, t => t.Id, s => s.Id)
.WhenMatched(
(t, s) => s.Price > t.Price,
then => then.Update(set => set.Set(t => t.Price, (t, s) => s.Price))
)
.WhenNotMatchedByTarget(then => then.Insert())
.WhenNotMatchedBySource(t => t.Category == "Seasonal", then => then.Delete())
.ToDataFrame(); // Or materialize directly to List<ProductItem> via .ToList()
Documentation & Guides
Comprehensive documentation, architecture references, and API catalogs are available on our documentation portal:
| Topic | Documentation Guide | Description |
|---|---|---|
| Quick Start | Quick Start Guide | 5-minute setup, core operations, and data ingestion |
| LINQ Provider | LINQ & Query CE | 3-tier compiler, BCL mappings, and pushdown architecture |
| Expressions | Expressions & Column Ops | Vectorized computations, string, date/time, and math functions |
| Lazy Execution | LazyFrame & Streaming | Predicate pushdown, projection pruning, and streaming engine |
| Lakehouse | Delta Lake & ACID Storage | Parquet scanning, Delta ACID transactions, and time-travel |
| Time Series | Time Series & Analytics | Dynamic groupby, rolling windows, and interpolation |
| Ecosystem | Ecosystem & Native Interop | Apache Arrow, ADO.NET, ML.NET, Tensor, and Spans |
| C# Idioms | Idiomatic C# Practices | SafeHandles, collection expressions, and fast-path row cursors |
| F# Idioms | Idiomatic F# Practices | Zero-allocation struct enumerators, modules, and pipeline operators |
| AI / LLMs | llms.txt | Curated context and anti-hallucination guardrails for LLM agents |
Project Architecture
Polars.NET uses a modular three-tier architecture to prevent upstream breaking changes:
+-------------------------------------------------------------------+
| Polars.NET User API Layer |
| - Polars.CSharp |
| - Polars.FSharp |
+-------------------------------------------------------------------+
|
v
+-------------------------------------------------------------------+
| Polars.NET.Core & Polars.NET.Linq |
| - Common Infrastructure, LINQ Provider written in F# |
| - Apache Arrow C Data Interface |
| - P/Invoke bindings and unsafe wrappers |
+-------------------------------------------------------------------+
|
v
+-------------------------------------------------------------------+
| Rust polars & delta-rs Engine |
| - Execution engine |
| - Physical query planner, optimizer |
| - delta-rs integration |
+-------------------------------------------------------------------+
Benchmarks
vs. Legacy .NET
<div align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="assets/benchmark_summary_dark.png"> <img alt="Speedup Summary vs Legacy .NET" src="assets/benchmark_summary_light.png" width="750" /> </picture> </div>
vs. Python Polars
<div align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="assets/benchmark_python_dark.png"> <img alt="Performance vs Python Polars" src="assets/benchmark_python_light.png" width="750" /> </picture> </div>
Delta Lake Read & Write vs Python Polars & PySpark
<div align="center"> <img alt="Delta Lake Read Benchmark" src="assets/read_benchmark.png" width="750" /> <br/><br/> <img alt="Delta Lake Write Benchmark" src="assets/write_benchmark.png" width="750" /> </div>
- Benchmark suite: Polars.NET-Benchmark
- Recipe repository: Polars.NET-Cookbook
Sponsoring
If Polars.NET is helpful to you, consider supporting the project via GitHub Sponsors to buy me a cup of black tea. Sláinte!
Acknowledgements
Polars.NET is built on:
- Polars (pola.rs) - The lightning-fast DataFrame library developed by Ritchie Vink and the Polars team.
- Apache Arrow - The columnar in-memory data standard powering zero-copy interop.
License
MIT License. See LICENSE for details.
Third-party licenses and notices are documented in 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 was computed. 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 was computed. 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. |
-
net8.0
- Apache.Arrow (>= 23.0.0)
- Apache.Arrow.Adbc (>= 0.24.0)
- Polars.NET.Core (>= 1.0.1)
- Polars.NET.Linq (>= 1.0.1)
- System.Numerics.Tensors (>= 10.0.5)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Polars.NET:
| Package | Downloads |
|---|---|
|
Altemiq.IO.Las.DataFrame
Provides support for reading LAS/LAZ to Polars data frames |
|
|
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 (1)
Showing the top 1 popular GitHub repositories that depend on Polars.NET:
| Repository | Stars |
|---|---|
|
JasonBock/Rocks
A mocking library based on the Compiler APIs (Roslyn + Mocks)
|
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.1 | 23 | 10/26/2026 |
| 1.0.0 | 89 | 10/24/2026 |
| 0.7.0 | 2,224 | 8/8/2026 |
| 0.6.0 | 829 | 6/9/2026 |
| 0.5.0 | 225 | 5/26/2026 |
| 0.4.0 | 2,930 | 3/20/2026 |
| 0.3.1 | 231 | 2/28/2026 |
| 0.3.0 | 501 | 2/26/2026 |
| 0.2.1-beta1 | 694 | 2/6/2026 |
| 0.2.0-beta1 | 223 | 2/4/2026 |
| 0.1.0-beta1 | 169 | 1/14/2026 |
| 0.1.0-alpha2 | 156 | 1/10/2026 |
| 0.1.0-alpha1 | 150 | 1/4/2026 |