Skip to content

Binary Formats and Web APIs (Parquet, pickle, requests)

Beyond CSV: faster and richer formats

CSV is human-readable but slow to parse and loses type information (everything comes back as text until pandas guesses otherwise). Once a project outgrows quick CSV exports, three tools solve different problems:

  • Binary formats (picklepickle, Parquet, HDF5) — faster reads/writes, types preserved.
  • Chunked reading (chunksizechunksize) — process files bigger than memory, piece by piece.
  • Web APIs (requestsrequests + JSON) — pull data directly from a live service instead of a file at all.

Pickle: quick, Python-only serialization

to_pickleto_pickle / read_pickleread_pickle dump a pandas object to disk (or any file-like object) almost instantly, preserving dtypes exactly:

pickle round-trip
import pandas as pd
import io
 
df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
 
buffer = io.BytesIO()
df.to_pickle(buffer)   # in real code: df.to_pickle("data.pkl")
 
buffer.seek(0)
restored = pd.read_pickle(buffer)   # in real code: pd.read_pickle("data.pkl")
print(restored)
pickle round-trip
import pandas as pd
import io
 
df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
 
buffer = io.BytesIO()
df.to_pickle(buffer)   # in real code: df.to_pickle("data.pkl")
 
buffer.seek(0)
restored = pd.read_pickle(buffer)   # in real code: pd.read_pickle("data.pkl")
print(restored)

Parquet and Feather: columnar, cross-language, fast

Apache Parquet (via to_parquetto_parquet / read_parquetread_parquet) stores data column-by-column with compression, keeping full type information — and unlike pickle, it’s readable from other languages (R, Spark, Java) too:

Parquet (requires the pyarrow package)
# pip install pyarrow  (or: conda install pyarrow)
df.to_parquet("data.parquet")
loaded = pd.read_parquet("data.parquet")
print(loaded.dtypes)
Parquet (requires the pyarrow package)
# pip install pyarrow  (or: conda install pyarrow)
df.to_parquet("data.parquet")
loaded = pd.read_parquet("data.parquet")
print(loaded.dtypes)

Feather (to_featherto_feather / read_featherread_feather) is a similar columnar format optimized for very fast reads/writes, most useful for short-lived caches between processing steps.

HDF5: many datasets in one file

HDF5 (via pandas.HDFStorepandas.HDFStore) is built for large arrays that don’t fit in memory — you can efficiently read a slice of a huge file without loading all of it:

HDFStore (requires the tables package)
# pip install tables
store = pd.HDFStore("mydata.h5")
store["prices"] = df          # write, dictionary-style
print(store["prices"])        # read back, dictionary-style
store.close()
HDFStore (requires the tables package)
# pip install tables
store = pd.HDFStore("mydata.h5")
store["prices"] = df          # write, dictionary-style
print(store["prices"])        # read back, dictionary-style
store.close()

HDF5 is best for “write-once, read-many” workloads — it isn’t a database, and concurrent writers can corrupt the file.

Reading huge files in chunks

For files too large to comfortably fit in memory, chunksizechunksize turns read_csvread_csv into an iterator — you process the file piece by piece instead of all at once:

Aggregating a file in chunks
import io
 
csv_text = "key,amount\nA,10\nB,20\nA,30\nC,40\nB,50\nA,60\n"
chunker = pd.read_csv(io.StringIO(csv_text), chunksize=2)  # 2 rows per chunk
 
totals = pd.Series([], dtype="int64")
for piece in chunker:
    totals = totals.add(piece.groupby("key")["amount"].sum(), fill_value=0)
 
print(totals.sort_values(ascending=False))
Aggregating a file in chunks
import io
 
csv_text = "key,amount\nA,10\nB,20\nA,30\nC,40\nB,50\nA,60\n"
chunker = pd.read_csv(io.StringIO(csv_text), chunksize=2)  # 2 rows per chunk
 
totals = pd.Series([], dtype="int64")
for piece in chunker:
    totals = totals.add(piece.groupby("key")["amount"].sum(), fill_value=0)
 
print(totals.sort_values(ascending=False))

Each piecepiece is a normal, small DataFrame — you aggregate it and merge the running total with .add(..., fill_value=0).add(..., fill_value=0), so no key is ever lost between chunks.

Pulling JSON from a web API

Many services expose data as a JSON HTTP response. The requestsrequests library fetches it; resp.json()resp.json() parses it into plain Python dicts/lists, which pd.DataFramepd.DataFrame can consume directly:

requests + DataFrame (illustrative — needs network access)
import requests
 
url = "https://api.github.com/repos/pandas-dev/pandas/issues"
resp = requests.get(url)
resp.raise_for_status()  # raise an error early if the request failed
 
data = resp.json()  # list of dicts, one per issue
issues = pd.DataFrame(data, columns=["number", "title", "state"])
print(issues.head())
requests + DataFrame (illustrative — needs network access)
import requests
 
url = "https://api.github.com/repos/pandas-dev/pandas/issues"
resp = requests.get(url)
resp.raise_for_status()  # raise an error early if the request failed
 
data = resp.json()  # list of dicts, one per issue
issues = pd.DataFrame(data, columns=["number", "title", "state"])
print(issues.head())

The exercises below simulate the parsed JSON as a plain Python list of dicts (exactly what resp.json()resp.json() would hand you), so you can practice the DataFrameDataFrame-building step without needing live network access.

Common pitfalls

  • Parquet and HDF5 both need an extra package installed (pyarrowpyarrow/fastparquetfastparquet, tablestables) — a missing package produces a clear ImportErrorImportError, not a silent failure.
  • Always call resp.raise_for_status()resp.raise_for_status() after requests.get()requests.get() — otherwise a failed request (like a 404) can silently hand you an error page instead of real data.
  • When processing chunks, remember each chunk is aggregated independently — you must combine the partial results yourself (as with .add(..., fill_value=0).add(..., fill_value=0) above).

Visualize it

diagram Choosing an I/O path mermaid
Different storage needs point to different tools — this is the decision flow behind picking pickle, Parquet, HDF5, chunked CSV reads, or a web API.

🧪 Try It Yourself

Exercise 1 – Round-Trip a DataFrame Through Pickle

Exercise 2 – Aggregate a File in Chunks

Exercise 3 – Turn a Parsed JSON Response Into a DataFrame

Next

With data loading covered end to end, move on to Correlation and Covariance to start measuring relationships between the columns you’ve loaded.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did