| name | apache-arrow |
| description | Expert guidance for Apache Arrow, the cross-language columnar memory format for analytics workloads. Helps developers use Arrow for high-performance data interchange between systems, zero-copy reads, and efficient columnar processing in Python (PyArrow) and JavaScript (Arrow JS). |
| compatibility | No special requirements |
| metadata | {"author":"terminal-skills","version":"1.0.0","category":"data","tags":["data-format","columnar","interop","python","javascript"],"source":{"repository":"https://github.com/TerminalSkills/skills","path":"skills/apache-arrow","license_path":"LICENSE","commit":"77fa0150aa0921f892420d3ec2a9204e3124b71e"}} |
Apache Arrow — Columnar Data Format
Overview
Apache Arrow, the cross-language columnar memory format for analytics workloads. Helps developers use Arrow for high-performance data interchange between systems, zero-copy reads, and efficient columnar processing in Python (PyArrow) and JavaScript (Arrow JS).
Instructions
PyArrow — Python Interface
import pyarrow as pa
import pyarrow.parquet as pq
import pyarrow.compute as pc
import pyarrow.csv as pcsv
table = pa.table({
"user_id": pa.array([1, 2, 3, 4, 5], type=pa.int64()),
"name": pa.array(["Alice", "Bob", "Charlie", "Diana", "Eve"]),
"revenue": pa.array([150.0, 320.5, 89.0, 1200.0, 45.5], type=pa.float64()),
"signup_date": pa.array([
"2026-01-15", "2026-01-20", "2026-02-01", "2026-02-10", "2026-03-01"
]).cast(pa.date32()),
"is_active": pa.array([True, True, False, True, False]),
})
high_value = pc.filter(table, pc.greater(table["revenue"], 100))
total_revenue = pc.sum(table["revenue"]).as_py()
avg_revenue = pc.mean(table["revenue"]).as_py()
sorted_table = pc.sort_indices(table, sort_keys=[("revenue", "descending")])
pq.write_table(table, "users.parquet", compression="zstd")
loaded = pq.read_table("users.parquet")
subset = pq.read_table(
"users.parquet",
columns=["user_id", "revenue"],
filters=[("revenue", ">", 100)],
)
csv_table = pcsv.read_csv("data.csv", convert_options=pcsv.ConvertOptions(
column_types={"amount": pa.float64(), "count": pa.int32()},
))
parquet_file = pq.ParquetFile("large_dataset.parquet")
for batch in parquet_file.iter_batches(batch_size=10_000):
filtered = pc.filter(batch, pc.greater(batch["amount"], 0))
process_batch(filtered)
Zero-Copy Interop
import pyarrow as pa
import pandas as pd
import polars as pl
arrow_table = pa.table({"x": [1, 2, 3], "y": [4.0, 5.0, 6.0]})
pandas_df = arrow_table.to_pandas()
arrow_from_pandas = pa.Table.from_pandas(pandas_df)
polars_df = pl.from_arrow(arrow_table)
arrow_from_polars = polars_df.to_arrow()
Partitioned Datasets
import pyarrow.dataset as ds
dataset = ds.dataset(
"s3://my-bucket/events/",
format="parquet",
partitioning=ds.partitioning(
pa.schema([
("year", pa.int32()),
("month", pa.int32()),
]),
flavor="hive",
),
)
scanner = dataset.scanner(
columns=["event_type", "user_id", "timestamp"],
filter=(ds.field("year") == 2026) & (ds.field("month") >= 1),
)
table = scanner.to_table()
ds.write_dataset(
table,
"output/events/",
format="parquet",
partitioning=ds.partitioning(
pa.schema([("year", pa.int32()), ("month", pa.int32())]),
flavor="hive",
),
existing_data_behavior="overwrite_or_ignore",
)
Arrow IPC (Inter-Process Communication)
import pyarrow as pa
import pyarrow.ipc as ipc
table = pa.table({"id": [1, 2, 3], "value": [10.0, 20.0, 30.0]})
with pa.OSFile("data.arrow", "wb") as f:
writer = ipc.new_file(f, table.schema)
writer.write_table(table)
writer.close()
sink = pa.BufferOutputStream()
writer = ipc.new_stream(sink, table.schema)
writer.write_table(table)
writer.close()
buffer = sink.getvalue()
reader = ipc.open_file("data.arrow")
loaded = reader.read_all()
JavaScript (Arrow JS)
import { tableFromIPC, tableToIPC } from "apache-arrow";
async function fetchArrowData(url: string) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
const table = tableFromIPC(new Uint8Array(buffer));
console.log(`Loaded ${table.numRows} rows, ${table.numCols} columns`);
console.log("Schema:", table.schema.fields.map((f) => `${f.name}: ${f.type}`));
const ids = table.getChild("id");
const values = table.getChild("value");
for (const row of table) {
console.log(row.toJSON());
}
return table;
}
async function sendArrowData(url: string, table: any) {
const buffer = tableToIPC(table);
await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/vnd.apache.arrow.stream" },
body: buffer,
});
}
Installation
pip install pyarrow
npm install apache-arrow
pip install duckdb
Examples
Example 1: Integrating Apache Arrow into an existing application
User request:
Add Apache Arrow to my Next.js app for the AI chat feature. I want streaming responses.
The agent installs the SDK, creates an API route that initializes the Apache Arrow client, configures streaming, selects an appropriate model, and wires up the frontend to consume the stream. It handles error cases and sets up proper environment variable management for the API key.
Example 2: Optimizing zero-copy interop performance
User request:
My Apache Arrow calls are slow and expensive. Help me optimize the setup.
The agent reviews the current implementation, identifies issues (wrong model selection, missing caching, inefficient prompting, no batching), and applies optimizations specific to Apache Arrow's capabilities — adjusting model parameters, adding response caching, and implementing retry logic with exponential backoff.
Guidelines
- Parquet for storage, Arrow for compute — Write Parquet to disk/S3; use Arrow in-memory for processing
- Column pruning — Always specify
columns= when reading Parquet; reading all columns wastes I/O and memory
- Predicate pushdown — Use
filters= in Parquet reads; the reader skips row groups that don't match
- Zero-copy when possible — Use
to_pandas(self_destruct=True) for large tables; Arrow can transfer memory ownership
- Batch processing for large files — Use
iter_batches() instead of reading entire files into memory
- IPC for microservices — Arrow IPC is faster than JSON/CSV for data exchange between services
- Partitioned datasets for scale — Partition by date/category; queries only scan relevant partitions
- DuckDB for Arrow queries — DuckDB can query Arrow tables directly with zero copy:
duckdb.arrow(table).query("SELECT ...")