astype
df['zip'] = df['zip'].astype(str)
df['count'] = df['count'].astype(int)
df['region'] = df['region'].astype('category')
astype is strict — a single bad value raises and nothing is converted.
A text column with few distinct values stored as category can use a fraction of the memory. Worth doing on region, status and similar fields in a large frame.
Dates
df['order_date'] = pd.to_datetime(df['order_date'])
df['order_date'] = pd.to_datetime(df['order_date'], format='%d/%m/%Y')
df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')
03/04/2024 is 3 April or 4 March depending on where the file came from. pandas guesses, and it can guess differently for different rows in the same column.
Always pass format= when you know it. Silent misparsing is far worse than an error.
Once converted, the .dt accessor opens up:
df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['weekday'] = df['order_date'].dt.day_name()
df['month_start'] = df['order_date'].dt.to_period('M').dt.to_timestamp()Numbers that will not convert
df['revenue'] = pd.to_numeric(df['revenue'], errors='coerce')
errors='coerce' turns anything unparseable into NaN instead of raising, which lets the rest of the column convert.
Then find out what failed:
bad = df[df['revenue'].isnull()]
Usually currency symbols, thousands separators or a stray footnote row. Clean them first:
df['revenue'] = (df['revenue'].astype(str)
.str.replace(r'[$,]', '', regex=True)
.pipe(pd.to_numeric, errors='coerce'))