1.4.7Python & Scientific Computing

Data loading (CSV, JSON, parquet)

2,927 words13 min readdifficulty · medium

What are these formats?

Figure — Data loading (CSV, JSON, parquet)

How to load each format

CSV loading — from first principles

Why CSV is row-oriented: When you write Alice,25,92.5, the computer reads left-to-right, one row at a time. Each row is independent. To get "all ages", the parser must scan every row.

Key parameters WHY:

  • dtype: Pre-specifying types skips Pandas' inference (which reads a sample, guesses, then reads again)—saves one full pass through data
  • parse_dates: Strings like "2023-01-01" stay as strings unless parsed—comparisons fail, sorting breaks
  • chunksize: Returns iterator, not DataFrame—enables processing datasets larger than RAM

JSON loading — hierarchical access

Why JSON is different: JSON can nest: {"user": {"name": "Alice", "prefs": {"theme": "dark"}}. This isn't a flat table. Pandas must flatten or preserve structure.

Orient options WHY:

  • orient='records': Each JSON object → one row (default for arrays of objects)
  • orient='index': Keys are row labels, values are row data
  • lines=True: Each line is a separate JSON object (JSONL format—streaming friendly, append-able)

Parquet loading — columnar efficiency

Why parquet is columnar: Traditional row format: [Alice|25|92.5][Bob|30|87.3]—reading "all ages" means parsing full rows. Columnar: [names: Alice,Bob][ages: 25,30][scores: 92.5,87.3]—reading "all ages" touches only the ages block.

Compression benefit: Column data is homogeneous (all ints, all floats)—compresses better than mixed-type rows.

Filters WHY:

  • filters=[('age', '>', 25)]: Parquet stores min/max stats per row group—can skip entire row groups without reading data (predicate pushdown)
  • Reading filtered data from CSV/JSON: must read entire file, then filter in memory

Format comparison — when to use what

| Format | Read Speed | Write Speed | Size | Nested Data | Type Safety | Use Case | |---------|------------|-------------|------|-------------|-------------| | CSV | Slow | Fast | Large| No | No (infer) | Interchange, human-readable | | JSON | Slow | Medium | Largest| Yes | Partial | APIs, hierarchical configs | | Parquet | Fast | Slow | Smallest| Partial | Yes | Analytics, archival, ML pipelines |

Derivation of size differences (example: 1M rows, 10 columns):

CSV: 
- Each value as text: "25" = 2 bytes + delimiter
- 1M × 10 × 3 bytes avg≈ 30MB uncompressed

JSON:
- Includes keys every row: {"age": 25} vs25
- Overhead ≈ 2-3× CSV
- 1M × 10 × 9 bytes ≈ 90MB uncompressed

Parquet:
- Columnar compression: RLE, dictionary encoding, bit-packing
- Typical: 5-10× smaller than CSV
- Same data≈ 3-6MB

Writing data

Performance tips — derived from format internals

  1. CSV: Use dtype parameter—inference scans twice, explicit types scan once
  2. JSON: Prefer JSONL (lines=True) for streaming—allows processing without loading entire array
  3. Parquet: Use columns parameter always—columnar format makes this nearly free
  4. Large files: Chunk CSV, use Parquet row groups, or switch to Dask/Polars for parallel loading
  5. Repeated access: Convert CSV → Parquet once, save 10-50× on subsequent reads

Derivation of CSV dtype speedup:

Without dtype:
1. Read 1000 sample rows → infer types (string? int? float?)
2. Seek to start
3. Read all rows, parse with inferred types
Total: 1 + N passes

With dtype={'age': int}:
1. Read all rows, parse with known types
Total: N passes

Speedup = (1 + N) / N → ~2× for large N (one less full read)
Recall Feynman explanation

Imagine you're moving to a new house. You have three ways to pack: CSV is like throwing everything into cardboard boxes with a label on top. Easy to pack, anyone can open a box and see what's inside by reading the label. But if you want to find all your books, you have to open every single box and dig through.

JSON is like using clear plastic bins with detailed labels on each item inside. You can see the structure—"this bin has books, and inside the book section there's a Harry Potter subsection." Great if things have natural groups, but takes more space because of all the labels.

Parquet is like a professional moving company that sorts everything by type into a warehouse. All books in one section, all clothes in another, all compressed into vacuum bags. Finding "all books" is instant—you just go to the book section. But you need special tools to pack and unpack it (can't just open it with a notepad like CSV).

When loading data, you're unpacking these boxes. CSV makes you unpack everything even if you want one thing. Parquet lets you grab just the section you need.

Connections

  • 1.4.05-NumPy-arrays-and-operations — Parquet stores NumPy arrays efficiently
  • 1.4.06-Pandas-DataFrames-and-operations — All loading produces DataFrames
  • 1.5.01-Handling-missing-data — CSV/JSON require explicit NA handling
  • 1.4.08-Data-cleaning-and-preprocessing — Loading is step1, cleaning is step 2
  • 2.3.05-Feature-engineeringtechniques — Parquet preserves feature types across pipeline steps
  • 3.1.02-TensorFlow-and-Keras-basics — TensorFlow can read Parquet directly with tf.data

#flashcards/ai-ml

What is the key structural difference between CSV and Parquet? :: CSV is row-oriented (each line = one record), Parquet is columnar (each column stored together). Reading one column from Parquet is fast; from CSV requires scanning all rows.

Why does Parquet load faster than CSV for specific columns?
Parquet stores separately with metadata indicating location. Reading one column = seeking to that column's blocks. CSV must parse entire rows to extract one column.
What does pd.read_csv('file.csv', dtype={'age': int}) optimize?
Skips Pandas' type inference step (which reads a sample, guesses types, then re-reads). Explicitly providing types eliminates one full file scan, ~2× speedup.
When should you use chunksize parameter in read_csv?
When the file is too large to fit in memory. chunksize=10000 loads 10k rows at a time, process each chunk, memory stays bounded regardless of file size.
What does pd.json_normalize(data) do?
Flattens nested JSON into a flat DataFrame. Converts {"user": {"name": "Alice"}} into columns like user.name or user_name (with sep parameter).
Why is JSON larger than CSV for tabular data?
JSON includes key names in every record: {"age": 25} vs CSV's 25. Overhead is ~2-3× for key repetition plus bracket/brace syntax.
What is predicate pushdown in Parquet?
Using filters like filters=[('age', '>', 25)] during read. Parquet row groups store min/max stats—can skip entire groups without reading data. Not possible in CSV (must read all, then filter).
Why use orient='records' for JSON?
Matches the common API format: array of objects [{...}, {...}]. Each object becomes one DataFrame row. Default for tabular JSON.
What does lines=True mean in read_json?
JSON Lines format (JSONL/NDJSON): each line is a separate JSON object, not wrapped in array. Enables streaming (don't load entire array), append-able (just add lines).
When should you convert CSV to Parquet?
When you'll read the data multiple times, especially selecting specific columns. Initial conversion takes time, but subsequent reads are 10-50× faster. Essential for ML pipelines.
What compression should you use for Parquet archival?
compression='gzip' for maximum compression (~5-10× smaller) when read speed is not critical. Use compression='snappy' (default) for balanced speed and size (~2-3× smaller).
Why does Parquet preserve data types but CSV doesn't?
Parquet stores schema in file metadata (column names, types, encoding). CSV is plain text—types must be inferred from content (ambiguous: "01234" could be int or string).
What is partitioned Parquet?
Splitting data into directories by column values: data/year=2024/, data/year=2025/. Reading with filters=[('year', '==', 2024)] only opens 2024 directory, skips rest—massive I/O savings for time-series or categorical grouping.
Why does usecols in read_csv still read the whole file?
CSV has no index or metadata. Parser must scan every row to find column positions, even if discarding most columns. Only memory savings, not I/O savings. Parquet's columnar structure enables true I/O skipping.

Concept Map

includes

includes

includes

determines

is

uses

enables

forces full scan for

loaded via

skips inference improves

huge files use

bounds memory in

dates need

Need multiple data formats

CSV text row-oriented

JSON hierarchical self-describing

Parquet columnar binary

Row scan reads all rows

Columnar layout skips columns

dtype pre-specify types

chunksize iterator

parse_dates

Load speed, memory, type preservation

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Data loading ka matlab hai ki ap apne analysis ya ML model ke liye external files se data ko memoryein late hain. Teen popular formats hain: CSV (sabse common, text-based), JSON (nested structure ke liye, APIs se ata hai), aur Parquet (analytics ke liye best, binary columnar format).

CSV simple hai—har line ek row, comma separate values. Lekin iska problem hai: types preserve nahi hote (sab kuch string jaisa dikhta hai initially), aur badi files ke liye slow hai kyunki row-by-row parse karna padta hai. Agar aapko sirf ek column chahiye (jaise sirf "age"), tab bhi puri file scan hogi. JSON hierarchical data handle kar sakta hai (nested objects, arrays), but size bahut bada ho jata hai kyunki har record mein keys repeat hotiain. APIs se data aata hai toh JSON natural choice hai.

Parquet ekdum different approach leta hai—yeh data ko columns mein store karta hai, rows mein nahi. Matlab agar 100 columns hain aur apko sirf "age" chahiye, toh sirf "age" wala block disk se read hoga, baki 99 skip. Isse speed10-50× badh jati hai badi files ke liye. Compression bhi bahut better hai (5-10× chhoti file). ML pipelines ya repeated analysis ke liye Parquet perfect hai—ek baar CSV se convert karo, phir hamesha fast load hoga.

Practical tip: Data aaye CSV mein (interchange easy hai), butagar baar-baar analysis karna hai toh turant Parquet mein convert kar lo. JSON use karo jab structure complex ho (config files, nested API responses). Parquet use karo jab performance critical ho—especially large datasets ya cloud storage (S3, GCS) pe, kyunki yeh selective column reads

Go deeper — visual, from zero

Test yourself — Python & Scientific Computing

Connections