On this page
How to Rename, Drop or Reorder Columns in a Parquet File
Why there is no "edit" button
A Parquet file stores its schema — column names, types, order — in the
footer, and every row group's column chunks are laid out to match it. No
mainstream tool patches that footer in place. Renaming cust_id to
customer_id, dropping a debug column or moving id to the front all mean
the same thing: read the file, write a new one with the changed schema.
That sounds expensive, but it is a single streaming pass. DuckDB rewrites a multi-GB file in seconds without holding it all in memory.
Check the current schema first
Before writing anything, confirm the exact column names and types. Drop the file into the Parquet Viewer to see the schema without installing anything, or run:
DESCRIBE SELECT * FROM 'events.parquet';
Column names are case-sensitive in many downstream engines, so copy them exactly.
DuckDB: one statement for every change
DuckDB's star modifiers let you express the change without listing every column:
-- Rename
COPY (
SELECT * RENAME (cust_id AS customer_id, ts AS event_time)
FROM 'events.parquet'
) TO 'events_v2.parquet' (FORMAT parquet, COMPRESSION zstd);
-- Drop
COPY (
SELECT * EXCLUDE (debug_payload, _tmp_flag)
FROM 'events.parquet'
) TO 'events_v2.parquet' (FORMAT parquet, COMPRESSION zstd);
-- Reorder: put id and event_time first, keep the rest as-is
COPY (
SELECT id, event_time, * EXCLUDE (id, event_time)
FROM 'events.parquet'
) TO 'events_v2.parquet' (FORMAT parquet, COMPRESSION zstd);
-- Change a type without touching the other columns
COPY (
SELECT * REPLACE (CAST(amount AS DECIMAL(18, 2)) AS amount)
FROM 'events.parquet'
) TO 'events_v2.parquet' (FORMAT parquet, COMPRESSION zstd);
The modifiers combine, so one pass can rename, drop and retype at once. You
can try the SELECT part in the SQL Workbench first to preview the
result in your browser, then run the COPY with the DuckDB CLI to produce
the new file.
For a partitioned dataset, do the same over a glob and write a new directory:
COPY (
SELECT * RENAME (cust_id AS customer_id)
FROM read_parquet('events/*/*.parquet', hive_partitioning = true)
) TO 'events_v2' (FORMAT parquet, PARTITION_BY (dt));
pyarrow: when you are already in Python
import pyarrow.parquet as pq
table = pq.read_table("events.parquet")
mapping = {"cust_id": "customer_id", "ts": "event_time"}
table = table.rename_columns([mapping.get(c, c) for c in table.column_names])
table = table.drop_columns(["debug_payload"])
table = table.select(["id", "event_time"] + [
c for c in table.column_names if c not in ("id", "event_time")
])
pq.write_table(table, "events_v2.parquet", compression="zstd")
Passing a list to rename_columns works on every pyarrow version; the
dict form only exists in recent releases. read_table loads the whole file
into memory, so for files larger than RAM, prefer the DuckDB route or
iterate with pq.ParquetFile(...).iter_batches() and a ParquetWriter.
What a rewrite can silently change
- Compression. DuckDB and pyarrow both default to Snappy, whatever the original file used. Pass the codec you actually want.
- Row group size. Readers that rely on row-group statistics to skip
data perform differently if groups get much larger or smaller. DuckDB
accepts
ROW_GROUP_SIZE 122880in theCOPYoptions. - Key-value metadata. The
pandasmetadata block (index columns, original dtypes) is not carried over by DuckDB. If a pandas consumer relied on it, rewrite with pyarrow from a pandas DataFrame instead. - Downstream queries. Every job selecting
cust_idbreaks. Renaming is a schema change; announce it like one.
Verify before you replace the original
Compare row counts and the new schema:
SELECT
(SELECT count(*) FROM 'events.parquet') AS before,
(SELECT count(*) FROM 'events_v2.parquet') AS after;
DESCRIBE SELECT * FROM 'events_v2.parquet';
If you only changed types, the Parquet Diff tool will show the re-typed columns from the footers and confirm that no rows were added or removed. Once the numbers match, move the new file over the old one.
Frequently asked questions
- Can I rename a column in a Parquet file without rewriting it?
- Not with standard tools. Column names live in the Thrift-encoded footer, and DuckDB, pyarrow, pandas and Spark all rename by writing a new file. Table formats like Delta Lake (column mapping) and Iceberg can rename through metadata instead.
- Does rewriting a Parquet file change the data?
- Values stay the same, but compression codec, row group size and key-value metadata such as the pandas index info come from the new writer's settings. Set them explicitly if downstream jobs depend on them.
- How do I rename a column in every file of a partitioned dataset?
- Read the whole dataset with a glob and hive_partitioning enabled, then COPY it back out with PARTITION_BY to a new directory. Swap the directories once you have checked the row count.
- Can I write the result back to the same file name?
- Write to a new path first, verify it, then move it over the original. Reading from and writing to the same file in one statement risks truncating the input before it has been fully read.