Loading data

Load a dataset's actual rows into pandas, polars, or DuckDB, run SQL directly against it, or export to CSV — plus how the API key and row limits work.

Loading a dataset's actual rows (.to_pandas(), .to_polars(), .to_duckdb(), .sql(), .to_csv()) requires a read-scoped API keyunless the dataset is currently keyless (ds.keyless), in which case no key is needed. Create a key from your Aesops account's API keys settings (see also the API's Authentication page).

client = Client(api_key="Aes_...")
ds = client.load_dataset("kenya-housing-prices")

pandas

df = ds.to_pandas()

Requires pandas (pip install 'aesops[pandas]').

polars

lf = ds.to_polars()

Requires polars (pip install 'aesops[polars]').

DuckDB

to_duckdb() returns an in-memory DuckDB connection with a data view bound to the dataset. DuckDB's httpfs extension does predicate + projection pushdown, so only the row-groups your query actually touches are fetched:

con = ds.to_duckdb()
con.sql("SELECT county, avg(price) FROM data GROUP BY county").df()

New to DuckDB or DuckDBPyRelation? See the DuckDB primer.

Running SQL directly

ds.sql() skips the intermediate con — same pushdown behavior, reference the dataset as data. Returns a DuckDBPyRelation; call .df() for pandas or .pl() for polars:

ds.sql("SELECT county, avg(price) FROM data GROUP BY 1").df()

# anything more specific than a simple limit — offset, filters, ordering —
# also goes through ds.sql() directly
ds.sql("SELECT * FROM data ORDER BY price DESC LIMIT 20").df()

CSV export

Client-side conversion — no extra server compute, DuckDB reads the Parquet directly and writes the CSV locally:

ds.to_csv("/tmp/housing.csv")

Limiting rows

to_pandas(), to_polars(), and to_csv() all take a limit kwarg. It's pushed down through read_parquet, so it also cuts what crosses the network — not just what lands in the DataFrame or file:

sample = ds.to_pandas(limit=100)
ds.to_polars(limit=100)
ds.to_csv("/tmp/sample.csv", limit=100)

On this page