Use df.select_dtypes(include=None, exclude=None) to select columns by their stored data type. Inspect the types first, choose include or exclude selectors and validate values before applying calculations or cleaning rules.
Inspect dtypes before choosing selectors. These dates explicitly use day/month/year, so parsing does not rely on locale or ambiguous inference. Text is explicitly stored as object in this first table to demonstrate the object selector.
import pandas as pd
import numpy as np
def student_data():
df = pd.DataFrame({
"NAME": pd.Series(["Ravi", "Raju", "Alex", "Ron", "King", "Jack"], dtype="object"),
"ID": [1, 2, 3, 4, 5, 6],
"MATH": [80, 40, 70, 70, 70, 30],
"Avg_mark": [45.5, 48.09, 50.12, 55.1, 50.6, 55.6],
"dt_start": pd.to_datetime(["1/1/2020", "2/1/2020", "5/1/2020", "11/7/2020", "15/8/2020", "31/12/2020"], format="%d/%m/%Y"),
"Exam": [True, False, True, True, False, False],
"dt": pd.to_timedelta(range(6), unit="D"),
"grade": pd.Categorical(["a", "c", "b", "b", "b", "c"])
})
return df
df = student_data()
print(df.dtypes)
assert df.loc[3, "dt_start"] == pd.Timestamp("2020-07-11")Expected output
NAME object
ID int64
MATH int64
Avg_mark float64
dt_start datetime64[us]
Exam bool
dt timedelta64[s]
grade category
dtype: objectinclude="int64" selects the columns with that compatible dtype. It selects columns, not rows, and does not convert numeric text to numbers. Use broader families when exact storage widths are not part of the requirement.
df = student_data()
result = df.select_dtypes(include="int64")
print(result)
assert result.columns.tolist() == ["ID", "MATH"]Expected output
ID MATH
0 1 80
1 2 40
2 3 70
3 4 70
4 5 70
5 6 30Supply a list to select more than one dtype. Boolean columns are not automatically included by the number family; choose bool explicitly when intended.
df = student_data()
result = df.select_dtypes(include=["int64", "bool"])
print(result)
assert result.columns.tolist() == ["ID", "MATH", "Exam"]Expected output
ID MATH Exam
0 1 80 True
1 2 40 False
2 3 70 True
3 4 70 True
4 5 70 False
5 6 30 Falseexclude returns the remaining columns. No source data are deleted. Explicit int64/float64 exclusions do not mean every possible numeric storage dtype.
df = student_data()
result = df.select_dtypes(exclude=["int64", "float64"])
print(result)
assert result.columns.tolist() == ["NAME", "dt_start", "Exam", "dt", "grade"]Expected output
NAME dt_start Exam dt grade
0 Ravi 2020-01-01 True 0 days a
1 Raju 2020-01-02 False 1 days c
2 Alex 2020-01-05 True 2 days b
3 Ron 2020-07-11 True 3 days b
4 King 2020-08-15 False 4 days b
5 Jack 2020-12-31 False 5 days cThe number family covers numeric dtypes, and can include timedeltas. Exclude timedelta when selecting ordinary measurements. Numeric identifiers may still be selected; dtype alone cannot distinguish an ID from a score.
df = student_data()
numeric = df.select_dtypes(include="number", exclude="timedelta")
print(numeric)
assert numeric.columns.tolist() == ["ID", "MATH", "Avg_mark"]
measurements = numeric.drop(columns=["ID"])
print("Measurement means:")
print(measurements.mean())Expected output
ID MATH Avg_mark
0 1 80 45.50
1 2 40 48.09
2 3 70 50.12
3 4 70 55.10
4 5 70 50.60
5 6 30 55.60
Measurement means:
MATH 60.000
Avg_mark 50.835
dtype: float64Use datetime, timedelta and category selectors for their respective columns. Timezone-aware datetime columns can be selected separately with datetimetz. For conversion rules, see to_datetime() and to_timedelta().
df = student_data()
print("Dates:")
print(df.select_dtypes(include="datetime"))
print("Durations:")
print(df.select_dtypes(include="timedelta"))
print("Categories:")
print(df.select_dtypes(include="category"))
assert df.select_dtypes(include="datetime").columns.tolist() == ["dt_start"]Expected output
Dates:
dt_start
0 2020-01-01
1 2020-01-02
2 2020-01-05
3 2020-07-11
4 2020-08-15
5 2020-12-31
Durations:
dt
0 0 days
1 1 days
2 2 days
3 3 days
4 4 days
5 5 days
Categories:
grade
0 a
1 c
2 b
3 b
4 b
5 cobject is not a text-only guarantee: it can store mixed numbers, lists or other Python objects. Dedicated string dtypes are separate from object; inference differs across Pandas versions. The example uses explicit object and string dtypes rather than depending on inference.
table = pd.DataFrame({
"object_text": pd.Series(["Pen", "Book"], dtype="object"),
"mixed": pd.Series(["A", 120], dtype="object"),
"string_text": pd.Series(["Mug", None], dtype="string"),
"quantity": [2, 3]
})
print(table.dtypes)
print("Object columns:")
print(table.select_dtypes(include="object"))
print("Dedicated string columns:")
print(table.select_dtypes(include="string"))
assert table.select_dtypes(include="object").columns.tolist() == ["object_text", "mixed"]
assert table.select_dtypes(include="string").columns.tolist() == ["string_text"]Expected output
object_text object
mixed object
string_text string
quantity int64
dtype: object
Object columns:
object_text mixed
0 Pen A
1 Book 120
Dedicated string columns:
string_text
0 Mug
1 <NA>Nullable Int64 and boolean dtypes support missing values. Test the selected column names rather than assuming all numeric columns use NumPy int64. See dtype inspection.
table = pd.DataFrame({"count": pd.Series([1, None], dtype="Int64"), "price": pd.Series([5.5, None], dtype="Float64"), "active": pd.Series([True, None], dtype="boolean")})
print(table.select_dtypes(include="number"))
print(table.select_dtypes(include="bool"))
assert table.select_dtypes(include="number").columns.tolist() == ["count", "price"]
assert table.select_dtypes(include="bool").columns.tolist() == ["active"]Expected output
count price
0 1 5.5
1 <NA> <NA>
active
0 True
1 <NA>At least one include or exclude selector is required. Overlapping include/exclude specifications raise an error. A valid selector with no matching columns returns an empty-column DataFrame, preserving the row index.
df = student_data()
for options in [{}, {"include": ["int64"], "exclude": ["int64"]}]:
try:
df.select_dtypes(**options)
except ValueError as error:
print(type(error).__name__ + ": " + str(error))
no_match = df.select_dtypes(include="complex")
print("No-match shape:", no_match.shape)
assert no_match.shape == (6, 0)Expected output
ValueError: at least one of include or exclude must be nonempty
ValueError: include and exclude overlap on frozenset({<class 'numpy.int64'>})
No-match shape: (6, 0)This synthetic extract has text identifiers, mixed numeric input and date text. Define the business schema and convert the specified fields before selecting numeric measurements. Selecting dtypes alone would miss unparsed numbers and include any numeric IDs.
raw = pd.DataFrame({"order_id": pd.Series(["0012", "0045", "0070"], dtype="string"), "quantity": ["2", "bad", "3"], "price": ["5.50", "8.00", "4.00"], "date": ["2026-01-02", "bad", "2026-01-04"]})
cleaned = raw.copy()
quantity = pd.to_numeric(raw["quantity"], errors="coerce")
integer_quantity = quantity.notna() & quantity.ge(0) & quantity.mod(1).eq(0)
cleaned["quantity"] = quantity.where(integer_quantity).astype("Int64")
cleaned["price"] = pd.to_numeric(raw["price"], errors="coerce").astype("Float64")
cleaned["date"] = pd.to_datetime(raw["date"], format="%Y-%m-%d", errors="coerce")
print(cleaned.dtypes)
numeric = cleaned.select_dtypes(include="number")
print(numeric)
assert numeric.columns.tolist() == ["quantity", "price"]
assert cleaned["order_id"].iloc[0] == "0012"Expected output
order_id string
quantity Int64
price Float64
date datetime64[us]
dtype: object
quantity price
0 2 5.5
1 <NA> 8.0
2 3 4.0A numeric dtype does not guarantee finite, non-negative or complete values. Validate the required fields and preserve failed rows. Use explicit quantity and price columns for revenue rather than blindly summing all numeric columns.
finite_price = pd.Series(np.isfinite(cleaned["price"].to_numpy(dtype=float, na_value=np.nan)), index=cleaned.index)
valid = (cleaned[["quantity", "price", "date"]].notna().all(axis=1)
& finite_price & cleaned["price"].ge(0)).fillna(False)
accepted = cleaned.loc[valid].copy()
accepted["revenue"] = accepted["quantity"] * accepted["price"]
print(accepted)
print("Review rows:")
print(raw.loc[~valid])
assert accepted["order_id"].tolist() == ["0012", "0070"]
assert accepted["revenue"].sum() == 23
# Optional Colab export:
# accepted.to_csv("typed_sales.csv", index=False)Expected output
order_id quantity price date revenue
0 0012 2 5.5 2026-01-02 11.0
2 0070 3 4.0 2026-01-04 12.0
Review rows:
order_id quantity price date
1 0045 bad 8.00 badselect_dtypes() chooses columns by stored type. astype() converts a chosen type; numeric and date parsers handle input formats. Range, format and completeness checks establish usability. Use info() to inspect the table before and after changes. Preserve original input so failed conversions can be reviewed.
Does select_dtypes() change types? No. Why is numeric text missing from the numeric selection? It has not been parsed into a numeric dtype. Why did an ID appear? Numeric storage does not imply measurement meaning. Why is object not all text? It allows arbitrary Python objects. Why did text selection change after a Pandas upgrade? String inference can change; inspect dtypes and use an explicit schema. How do I store changes? Assign converted fields explicitly to the intended DataFrame; do not assume editing a selected table updates its source.
Create code as nullable string, quantity as nullable Int64, price as float and active as bool. Select numeric fields and Boolean fields separately. Expect quantity/price and active respectively.
The explicit text identifier remains outside the numeric selection.
practice = pd.DataFrame({"code": pd.Series(["0012", "0045"], dtype="string"), "quantity": pd.Series([2, None], dtype="Int64"), "price": [5.5, 8.0], "active": [True, False]})
print(practice.select_dtypes(include="number"))
print(practice.select_dtypes(include="bool"))
assert practice.select_dtypes(include="number").columns.tolist() == ["quantity", "price"]
assert practice.select_dtypes(include="bool").columns.tolist() == ["active"]Expected output
quantity price
0 2 5.5
1 <NA> 8.0
active
0 True
1 FalseOpen in Google Colab View on GitHub
Run the examples in order, change selectors and input types, then compare selected columns and failed conversions. Save your own copy to keep edits. All sample tables are included in the notebook.
Continue with Data Cleaning, Data Analysis, dtypes, astype() and timedelta data.
Reference: Pandas DataFrame.select_dtypes documentation.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.