Pandas get_dummies(): Encode Categories with Practical Examples

Use pd.get_dummies() to turn categories into indicator columns. Choose the dtype, handle missing labels and keep a consistent category schema across datasets.

Create the student table 🔝

Call the top-level function pd.get_dummies(). It returns a new DataFrame without changing the source.

import pandas as pd
students = pd.DataFrame({
    "ID": [1, 2, 3, 4, 5, 6],
    "MATH": [80, 40, 70, 70, 70, 30],
    "CLASS1": ["Four", "Three", "Three", "Four", "Five", "Three"]
})
print(students)

Expected output

   ID  MATH CLASS1
0   1    80   Four
1   2    40  Three
2   3    70  Three
3   4    70   Four
4   5    70   Five
5   6    30  Three

Choose the options 🔝

data accepts an array-like object, Series or DataFrame. columns selects fields to encode. prefix and prefix_sep control labels; the default separator is an underscore. dummy_na adds a missing-value indicator. sparse uses sparse arrays. drop_first removes the first category indicator. dtype controls new indicator columns; the default is bool.

Encode categories with Boolean indicators 🔝

By default, object, string and category columns are encoded, while numeric columns remain unchanged. True indicates a matching category.

encoded = pd.get_dummies(students)
print(encoded)
assert encoded["CLASS1_Four"].tolist() == [True, False, False, True, False, False]
assert encoded["MATH"].equals(students["MATH"])

Expected output

   ID  MATH  CLASS1_Five  CLASS1_Four  CLASS1_Three
0   1    80        False         True         False
1   2    40        False        False          True
2   3    70        False        False          True
3   4    70        False         True         False
4   5    70         True        False         False
5   6    30        False        False          True

Use explicit integer indicators 🔝

Specify dtype="int64" for 0 and 1 output. The meaning is the same as Boolean indicators.

encoded = pd.get_dummies(students, dtype="int64")
print(encoded)
assert encoded["CLASS1_Five"].tolist() == [0, 0, 0, 0, 1, 0]

Expected output

   ID  MATH  CLASS1_Five  CLASS1_Four  CLASS1_Three
0   1    80            0            1             0
1   2    40            0            0             1
2   3    70            0            0             1
3   4    70            0            1             0
4   5    70            1            0             0
5   6    30            0            0             1

Change prefix and separator 🔝

A prefix replaces the original field-name prefix. Set prefix_sep to choose the separator independently.

print(pd.get_dummies(students, prefix="my", dtype="int64"))
print(pd.get_dummies(students, prefix="my", prefix_sep="-", dtype="int64"))

Expected output

   ID  MATH  my_Five  my_Four  my_Three
0   1    80        0        1         0
1   2    40        0        0         1
2   3    70        0        0         1
3   4    70        0        1         0
4   5    70        1        0         0
5   6    30        0        0         1
   ID  MATH  my-Five  my-Four  my-Three
0   1    80        0        1         0
1   2    40        0        0         1
2   3    70        0        0         1
3   4    70        0        1         0
4   5    70        1        0         0
5   6    30        0        0         1

Select numeric categories explicitly 🔝

Explicit columns can include numeric fields. Encoding marks as categories removes numeric ordering and can create many columns; keep continuous measures numeric unless discrete categories are intended. Distinct prefixes prevent ambiguous labels.

encoded = pd.get_dummies(students, columns=["CLASS1", "MATH"],
    prefix={"CLASS1": "my", "MATH": "mark"}, dtype="int64")
print(encoded)
assert "MATH" not in encoded.columns
assert encoded["mark_70"].sum() == 3

Expected output

   ID  my_Five  my_Four  my_Three  mark_30  mark_40  mark_70  mark_80
0   1        0        1         0        0        0        0        1
1   2        0        0         1        0        1        0        0
2   3        0        0         1        0        0        1        0
3   4        0        1         0        0        0        1        0
4   5        1        0         0        0        0        1        0
5   6        0        0         1        1        0        0        0

Use sparse output 🔝

Sparse arrays can help with many mostly-zero indicators. Measure memory with your data and check compatibility with the next tool; sparse output is not automatically smaller for every table.

encoded = pd.get_dummies(students, prefix="my", sparse=True, dtype="int64")
print(encoded)
print("Indicator dtype:", encoded["my_Four"].dtype)
assert isinstance(encoded["my_Four"].dtype, pd.SparseDtype)

Expected output

   ID  MATH  my_Five  my_Four  my_Three
0   1    80        0        1         0
1   2    40        0        0         1
2   3    70        0        0         1
3   4    70        0        1         0
4   5    70        1        0         0
5   6    30        0        0         1
Indicator dtype: Sparse[int64, 0]

Choose whether to drop the first category 🔝

Five is omitted for these text values. All-zero indicators represent that category when there are no missing values. Some modelling designs use k-1 indicators; this is not required for every analysis.

encoded = pd.get_dummies(students, prefix="my", drop_first=True, dtype="int64")
print(encoded)
assert "my_Five" not in encoded.columns
assert encoded.loc[4, ["my_Four", "my_Three"]].sum() == 0

Expected output

   ID  MATH  my_Four  my_Three
0   1    80        1         0
1   2    40        0         1
2   3    70        0         1
3   4    70        1         0
4   5    70        0         0
5   6    30        0         1

Handle missing categories 🔝

Without dummy_na, a missing value produces all-zero indicators. dummy_na=True adds a missing indicator even when there are no missing values. With drop_first as well, a missing indicator distinguishes missing rows from the omitted category.

labels = pd.Series(["Book", "Pen", None, "Book"], dtype="string")
plain = pd.get_dummies(labels, prefix="product", dtype="int64")
explicit = pd.get_dummies(labels, prefix="product", dummy_na=True, dtype="int64")
print("Without missing indicator:")
print(plain)
print("With missing indicator:")
print(explicit)
assert plain.loc[2].sum() == 0
assert explicit.loc[2].sum() == 1

Expected output

Without missing indicator:
   product_Book  product_Pen
0             1            0
1             0            1
2             0            0
3             1            0
With missing indicator:
   product_Book  product_Pen  product_<NA>
0             1            0             0
1             0            1             0
2             0            0             1
3             1            0             0

Define category order and unused categories 🔝

An explicit category definition controls indicator order and the category omitted by drop_first. Unknown labels become missing during categorical conversion, so validate them first.

kind = pd.CategoricalDtype(categories=["Four", "Three", "Five"], ordered=False)
classes = students["CLASS1"].astype(kind)
encoded = pd.get_dummies(classes, prefix="class", drop_first=True, dtype="int64")
print(encoded)
assert encoded.columns.tolist() == ["class_Three", "class_Five"]

Expected output

   class_Three  class_Five
0            0           0
1            1           0
2            1           0
3            0           0
4            0           1
5            1           0

Practical example: normalize sales channels 🔝

This synthetic table includes inconsistent labels, a missing value and an unexpected channel. Normalize under a defined policy and retain source rows for review. See Data Cleaning and text case operations.

raw = pd.DataFrame({
    "order_id": [101, 102, 103, 104, 105],
    "channel": [" Web ", "STORE", "web", None, "fax"],
    "amount": [20, 35, 15, 10, 8]
})
channel = raw["channel"].astype("string").str.strip().str.lower()
channel = channel.mask(channel.eq(""))
allowed = ["web", "store", "phone"]
unknown = channel.notna() & ~channel.isin(allowed)
review = raw.loc[channel.isna() | unknown].copy()
print("Unknown IDs:", raw.loc[unknown, "order_id"].tolist())
print(review)
assert review["order_id"].tolist() == [104, 105]

Expected output

Unknown IDs: [105]
   order_id channel  amount
3       104     NaN      10
4       105     fax       8

Encode approved channels with a fixed schema 🔝

Keep known approved channels for this report. Phone is a valid category even though absent from the accepted rows. Keep order IDs for tracing records, not as categories to encode.

accepted = raw.loc[channel.notna() & ~unknown].copy()
accepted["channel"] = pd.Categorical(channel.loc[accepted.index], categories=allowed)
features = pd.get_dummies(accepted, columns=["channel"], prefix="channel", dtype="int64")
indicator_columns = ["channel_web", "channel_store", "channel_phone"]
print(features)
assert features["order_id"].tolist() == [101, 102, 103]
assert features[indicator_columns].sum(axis=1).eq(1).all()
assert len(accepted) + len(review) == len(raw)

Expected output

   order_id  amount  channel_web  channel_store  channel_phone
0       101      20            1              0              0
1       102      35            0              1              0
2       103      15            1              0              0

Apply the same schema to another batch 🔝

Independent encoding can create different columns. Validate labels before applying saved categories, then use the agreed indicator order. For modelling, learn preprocessing from training data or a predefined schema rather than held-out evaluation data.

later = pd.DataFrame({"channel": ["phone", "web"]})
assert later["channel"].isin(allowed).all()
later["channel"] = pd.Categorical(later["channel"], categories=allowed)
later_features = pd.get_dummies(later, columns=["channel"], prefix="channel", dtype="int64")
later_features = later_features.reindex(columns=indicator_columns, fill_value=0)
print(later_features)
assert later_features["channel_phone"].tolist() == [1, 0]

Expected output

   channel_web  channel_store  channel_phone
0            0              0              1
1            1              0              0

Check category counts and export 🔝

With one category per row and drop_first=False, every accepted row has one active indicator. Use value_counts() for simple frequencies and groupby() for revenue summaries. See Input and Output for files.

counts = features[indicator_columns].sum()
print(counts)
print(features.to_csv(index=False).rstrip())
assert counts.sum() == len(accepted)
assert counts["channel_web"] == 2
# Optional Colab export:
# features.to_csv("encoded_sales_channels.csv", index=False)

Expected output

channel_web      2
channel_store    1
channel_phone    0
dtype: int64
order_id,amount,channel_web,channel_store,channel_phone
101,20,1,0,0
102,35,0,1,0
103,15,1,0,0

Common questions 🔝

Does encoding clean labels? No; normalize first under a defined policy. Why is a numeric field unchanged? Select it explicitly in columns to encode it. Should I encode customer IDs? Usually they identify records; high cardinality can create excessive columns. Does a multiword value split into categories? No; each whole value is a category. Why do batches have different columns? Their observed categories may differ; use a validated schema. Continue with unique(), cut(), row selection, plots, mean(), min(), sum() and text lengths.

Exercise: encode delivery modes 🔝

Encode pickup, delivery, pickup and a missing value using integer indicators and dummy_na=True. Predict the row sums and pickup count.

Exercise solution 🔝

Each row has one active indicator, including the missing row. Pickup occurs twice.

modes = pd.Series(["pickup", "delivery", "pickup", None], dtype="string")
answer = pd.get_dummies(modes, prefix="mode", dummy_na=True, dtype="int64")
print(answer)
print("Row sums:", answer.sum(axis=1).tolist())
assert answer.sum(axis=1).tolist() == [1, 1, 1, 1]
assert answer["mode_pickup"].sum() == 2

Expected output

   mode_delivery  mode_pickup  mode_<NA>
0              0            1          0
1              1            0          0
2              0            1          0
3              0            0          1
Row sums: [1, 1, 1, 1]

Practice in Google Colab 🔝

Open in Google Colab View on GitHub
Run the examples in order, change channels and category definitions, then inspect indicators and review rows. Save your own copy to keep edits. All sample tables are included in the notebook.

Continue with the Data Cleaning hub, where(), loc, at, NumPy where(), fillna() and iloc.

Reference: Pandas get_dummies documentation.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer