iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

DataFrame

A pandas DataFrame is a 2-D labelled table — rows + named columns, mixed dtypes per column. The Swiss-army workhorse of analytics: load, clean, transform, group, plot.

Create, inspect, select, mutate

EXAMPLE
import pandas as pd
import numpy as np

# 1) Create
# From a dict of columns
df = pd.DataFrame({
    'name': ['Ada', 'Bo', 'Cy', 'Di'],
    'age':  [32, 28, 41, 22],
    'city': ['Sydney', 'Sydney', 'Melbourne', 'Brisbane'],
})

# From a list of records
df = pd.DataFrame.from_records([
    {'name': 'Ada', 'age': 32},
    {'name': 'Bo',  'age': 28},
])

# From CSV / JSON / Parquet
df = pd.read_csv('users.csv', parse_dates=['signup_at'])
df = pd.read_json('users.json')
df = pd.read_parquet('users.parquet')

# 2) Inspect
df.head()
df.tail(3)
df.shape          # (rows, cols)
df.columns
df.dtypes
df.info()
df.describe()     # summary stats for numeric
df.memory_usage(deep=True)

# 3) Select columns
df['name']                            # Series
df[['name', 'age']]                   # DataFrame
df.name                                # attribute access (only if name is a valid identifier)

# 4) Filter rows — boolean mask
df[df['age'] >= 30]
df[(df['age'] >= 30) & (df['city'] == 'Sydney')]
df[df['city'].isin(['Sydney', 'Brisbane'])]
df[df['name'].str.startswith('A')]

# 5) Position vs label
df.iloc[0]                            # first row by position
df.iloc[:5, :2]                        # first 5 rows, first 2 cols
df.loc[0, 'name']                      # cell by label
df.loc[df['age'] >= 30, ['name', 'city']]

# 6) Add / modify columns
df['adult']      = df['age'] >= 18
df['decade']     = df['age'] // 10
df['fullname']   = df['name'] + ' ' + df['city']
df = df.assign(
    score = lambda x: x['age'] * 2,
    tag   = lambda x: np.where(x['adult'], 'A', 'M'),
)

# 7) Rename + drop
df = df.rename(columns={'name': 'first_name'})
df = df.drop(columns=['decade'])
df = df.drop(index=[0, 3])

# 8) Missing data
df.isna().sum()                            # NA per column
df = df.dropna(subset=['age'])             # drop rows missing age
df['age'] = df['age'].fillna(df['age'].median())
df['city'] = df['city'].fillna('Unknown')

# 9) Types
df['age'] = df['age'].astype('Int32')      # nullable int
df['city'] = df['city'].astype('category')
df['signup_at'] = pd.to_datetime(df['signup_at'])

# 10) Sort
df = df.sort_values(['city', 'age'], ascending=[True, False])

# 11) Aggregations
df['age'].mean()
df['age'].quantile([0.25, 0.5, 0.75])
df['city'].value_counts()

# 12) Group-by (intro — see groupby lesson for details)
df.groupby('city').agg({'age': 'mean', 'name': 'count'})

# 13) Reshape
wide = df.pivot_table(values='age', index='city', columns='adult', aggfunc='mean')
long = wide.reset_index().melt(id_vars='city')

# 14) Merge / join
other = pd.DataFrame({'city': ['Sydney', 'Brisbane'], 'population': [5_000_000, 2_500_000]})
merged = df.merge(other, on='city', how='left')

# 15) Export
df.to_csv('out.csv', index=False)
df.to_parquet('out.parquet')
df.to_json('out.json', orient='records')

# 16) Performance — vectorise!
df['adult'] = df['age'] >= 18                           # vectorised, fast
# vs:
df['adult'] = df.apply(lambda r: r.age >= 18, axis=1)   # row-by-row, slow
# For very large data, look at polars / DuckDB.

Why it matters

Vectorised ops on Series / DataFrame are 10-100× faster than .apply per row. If you’re writing .apply(lambda r: ...), look for a column-level expression first — pandas usually has one.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import pandas as pd
df = pd.DataFrame({
    'name': ['Ada', 'Bo', 'Cy'],
    'age':  [36, 28, 22],
})
print(df)
print(df.dtypes)
Try it Yourself »

Exercise

Load a CSV into a DataFrame.

df = pd. ('users.csv')

Test yourself

Q1. Most idiomatic constructor is…
Q2. Label-based row selection uses…
Q3. See the first 5 rows with…

Discussion

Loading…