cut and qcut
pd.cut(x, bins, labels) assigns each value to a fixed interval you define (for example age bands), while pd.qcut(x, q) splits values into q groups with roughly equal counts (quartiles, deciles). Both return a categorical Series you can group by.
Syntax
pd.cut(x, bins, labels=None, right=True, include_lowest=False) | pd.qcut(x, q, labels=None, duplicates="raise")| Part | What it is |
|---|---|
bins | cut: number of equal-width bins or a list of edges |
q | qcut: number of quantiles, or a list of quantile points like [0, .5, 1] |
labels | Names for the bins; False returns integer codes |
right | cut: True makes intervals closed on the right, (a, b] |
include_lowest | cut: include the first edge in the first bin |
Examples
import pandas as pd
df = pd.DataFrame({"age": [5, 17, 25, 40, 67]})
df["band"] = pd.cut(df["age"], bins=[0, 17, 64, 120], labels=["child", "adult", "senior"])
dfResult: age band 0 5 child 1 17 child 2 25 adult 3 40 adult 4 67 senior
Edges are right-closed: 17 falls in (0, 17], the child band.
pd.cut(df["age"], bins=[0, 17, 64, 120]).tolist()Result: [Interval(0, 17, closed='right'), Interval(0, 17, closed='right'), Interval(17, 64, closed='right'), Interval(17, 64, closed='right'), Interval(64, 120, closed='right')]
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8])
pd.qcut(s, 4, labels=["Q1", "Q2", "Q3", "Q4"]).tolist()Result: ['Q1', 'Q1', 'Q2', 'Q2', 'Q3', 'Q3', 'Q4', 'Q4']
Quartiles: two values in each bin.
Common mistakes
- NaN for the smallest value: with right=True the lowest edge is excluded; pass include_lowest=True or start the bins lower.
- ValueError: Bin edges must be unique in qcut: many repeated values; pass duplicates="drop" or use fewer quantiles.
- ValueError: Bin labels must be one fewer than the number of bin edges: four edges define three bins, so pass three labels.
Practice cut and qcut
These drills check your answer on live data, free, no account needed.
- Quartile bins with qcutSplit customers into four groups with equal numbers of customers by `spend`, labeled "Q1" (lowest) to "Q4" (highest). Return the labels as a Series.
- Age bands with cutLabel each age with a band using the edges 0, 18, 35, 60 and 120 and the labels "child", "young adult", "adult" and "senior". Each band includes its upper edge (18 is a child, 35 is a young adult). Return a Series.
Questions
cut or qcut?
cut when the boundaries have meaning (age bands, price tiers); qcut when you want equal-sized groups like quartiles or deciles regardless of the values.
How do I bin into equal-width intervals automatically?
pd.cut(s, bins=5) splits the range from min to max into five equal-width intervals.
Related
- value_countsHow to count values in a pandas column with value_counts: counts sorted by frequency, percentages with normalize=True, including NaN, and two-column combos.
- groupbyHow groupby works in pandas: group by one or more columns, apply sum, mean, count or size, get a flat table with as_index=False, and iterate over groups.
- rankHow to rank in pandas with rank: ascending or descending, tie methods (average, min, dense, first), ranking within groups, percentile ranks, integer output.
- applyHow to use apply in pandas on a Series or DataFrame, with axis=1 for row-wise logic, lambdas, returning several columns, and why vectorized code is faster.