Blazing Fast & Memory Efficient
Powered by the Polars Rust core and Apache Arrow columnar format with multi-threaded SIMD, query optimization, and streaming execution.
Rust Core. Arrow Memory. Native Speed.
Write queries in the style most natural to your project. Polars.NET executes C# Fluent calls, F# functional pipelines, C# LINQ syntax, and F# computation expressions with identical, zero-copy native performance:
using Polars.CSharp;
using static Polars.CSharp.Polars;
// Ingest from strongly-typed records or anonymous objects
var df = DataFrame.FromColumns(new
{
Date = new[] { "2023-01-01", "2023-01-01", "2023-01-02" },
City = new[] { "London", "Manchester", "London" },
Temperature = new[] { 10.5, 9.0, 12.1 },
Rain = new[] { true, true, false }
}).WithColumn(Col("Date").Str.ToDate("%Y-%m-%d"));
// Filter, GroupBy & Aggregate with multi-threaded SIMD execution
var result = df.Lazy()
.Filter(Col("Temperature") > 9.5)
.GroupBy("City")
.Agg(
Col("Temperature").Mean().Alias("Avg_Temperature"),
Col("Temperature").Count().Alias("Record_Count")
)
.Sort("Avg_Temperature", descending: true)
.Collect();open Polars.FSharp
type Weather = { Date: string; City: string; Temperature: float; Rain: bool }
let data = [
{ Date="2023-01-01"; City="London"; Temperature=10.5; Rain=true }
{ Date="2023-01-01"; City="Manchester"; Temperature=9.0; Rain=true }
{ Date="2023-01-02"; City="London"; Temperature=12.1; Rain=false }
]
// Idiomatic functional pipelines with pl.* combinators
let result =
DataFrame.ofRecords data
|> DataFrame.withColumn (pl.col("Date").Str.ToDate "%Y-%m-%d")
|> DataFrame.filter (pl.col "Temperature" .> pl.lit 9.5)
|> DataFrame.groupBy [ pl.col "City" ]
|> DataFrame.agg [
pl.col("Temperature").Mean().Alias "Avg_Temperature"
pl.col("Temperature").Count().Alias "Record_Count"
]
|> DataFrame.sortDescending [ pl.col "Avg_Temperature" ]using Polars.CSharp;
using Polars.CSharp.Linq;
// Standard C# LINQ with 100% Native Pushdown to the Rust engine
var result = (from r in df.AsQueryable<WeatherRecord>()
where r.Temperature > 9.5
group r by r.City into g
select new {
City = g.Key,
Avg_Temperature = g.Average(x => x.Temperature),
Record_Count = g.Count()
})
.ToDataFrame()
.Sort("Avg_Temperature", descending: true);open Polars.FSharp
open Polars.FSharp.Query
// Native F# query { } computation expression
let result =
query {
for r in df.AsQueryable<Weather>() do
where (r.Temperature > 9.5)
groupValBy r r.City into g
select {|
City = g.Key
Avg_Temperature = g.Average(fun x -> x.Temperature)
Record_Count = g.Count()
|}
}
|> Query.toDataFrame
|> DataFrame.sortDescending [ pl.col "Avg_Temperature" ]| Citystr | Avg_Temperaturef64 | Record_Countu32 |
|---|---|---|
| London | 11.3 | 2 |
| Feature | Standard .NET DataFrames | Polars.NET |
|---|---|---|
| Execution Core | Interpreted managed loops | Multi-threaded vectorized Rust SIMD |
| Memory Model | Managed object allocations (GC pressure) | Arrow columnar layout with zero-copy FFI |
| Query Optimization | None (client-side execution) | Logical plan optimization, Predicate & Projection pushdown |
| Out-of-Core Processing | Out of Memory (OOM) on large files | Streaming engine & Chunked memory |
| Language Paradigms | Basic C# collection methods | C# Fluent API, F# Pipelines, C# LINQ, and F# Query CE |
| Lakehouse & Big Data | Requires Spark / JVM wrappers | Native Delta Lake ACID storage, ADBC, & Arrow IPC |
Ready to build blazingly fast data pipelines? Read the Quick Start Guide or explore the Core Concepts.
Polars.NET brings the blazing speed, Arrow memory layout, and query optimization of the world-class Polars DataFrame engine to the .NET ecosystem. We express our deepest gratitude to Ritchie Vink and the entire Polars open-source community for their pioneering work on high-performance columnar data processing.