Written and maintained by CASRAI Editorial Board
Last updated
pandas dtypes are the data types pandas assigns to each column of a Series or DataFrame. Inspect them with df.dtypes, convert them with astype(), pd.to_numeric() or pd.to_datetime(), and filter columns by type with select_dtypes(). This guide is for researchers and analysts loading survey, instrument or administrative exports into pandas who need every column to carry the type the analysis expects. Commands were checked against the pandas user guide and API reference, and the examples were run on pandas 3.0.5.
What dtypes are used for in research
A column’s dtype decides which operations work and how missing values are stored. A participant ID such as 007 stored as an integer loses its leading zeros; a Likert response exported as text cannot be averaged; a date left as a string cannot be sorted or resampled. Checking dtypes right after loading is a cheap data-quality step, and it belongs alongside the other data cleaning steps.
pandas supports two families of dtypes. NumPy-backed dtypes cover float, int, bool, timedelta64[ns] and datetime64[ns]; NumPy has no timezone-aware datetime. Extension dtypes add timezone-aware datetimes, categoricals, periods, intervals, sparse data, nullable integers and floats, strings and nullable booleans.
Install or access
pandas is open-source and installed from the official channels on the pandas installation page: pip install pandas or conda install -c conda-forge pandas. Confirm the version with import pandas as pd; print(pd.__version__), because string handling differs between pandas 2.x and 3.x (see “Strings: object versus str” below).
Step by step: inspect and convert dtypes
- Inspect. Run
df.dtypesfor one dtype per column, ordf.info()for dtypes plus non-null counts. - Convert with
astype(). The signature isDataFrame.astype(dtype, copy=<no_default>, errors='raise'). Pass one dtype for the whole frame (df.astype("int32")) or a mapping from column name to dtype (df.astype({"col1": "int32"})); columns not in the mapping are unchanged, and a key that is not a column raisesKeyError. A Series converts the same way:ser.astype("category"). - Convert dirty text with the
to_*functions.pd.to_numeric,pd.to_datetimeandpd.to_timedeltaare the “hard” conversions and work on one-dimensional input (usedf.applyfor a whole frame). The defaulterrors='raise'stops at the first bad value;errors='coerce'turns unparseable values intoNaNorNaT. For examplepd.to_numeric(["apple", 2, 3], errors="coerce")returnsarray([nan, 2., 3.]). For date parsing see pandas datetime. - Let pandas infer with
infer_objects(). It soft-converts object columns to a better dtype where the values allow. - Select columns by type.
df.select_dtypes(include=["number", "bool"])keeps matching columns;exclude=drops them."number"expands to the NumPy numeric child types.
Worked example on survey-style data
import pandas as pddf = pd.DataFrame({ "id": ["001", "002", "003"], "score": ["4", "5", "n/a"], "wave": ["a", "b", "a"],})df["score"] = pd.to_numeric(df["score"], errors="coerce") # float64: 4.0, 5.0, NaNdf["score"] = df["score"].astype("Int64") # nullable: 4, 5, <NA>df["wave"] = df["wave"].astype("category")
Run on pandas 3.0.5, all three columns load as str. The id column is deliberately left as text so that 001 keeps its zeros. After to_numeric with errors="coerce", score is float64 because NaN is a float; casting to the nullable Int64 restores integer values and stores the missing entry as <NA>.
Output and how to read it
Common dtypes and their aliases
| Dtype | String alias | Typical research use (editorial guidance) |
|---|---|---|
| int64 / float64 | "int64", "float64" |
Counts and measurements; the defaults for integers and floats regardless of platform. |
| Nullable integer | "Int8" to "Int64", "UInt8" to "UInt64" |
Whole-number responses or counts that can be missing. |
| Nullable float | "Float32", "Float64" |
Measurements with proper missing-value handling. |
| BooleanDtype | "boolean" |
Yes/no flags that may be missing. |
| StringDtype | "string" |
Identifiers and free text. |
| CategoricalDtype | "category" |
Study arm, site, wave, coded responses. |
| datetime64[ns] | "datetime64[ns]" |
Timestamps without a timezone. |
| DatetimeTZDtype | "datetime64[ns, <tz>]" |
Timestamps with a timezone. |
| PeriodDtype / IntervalDtype | "period[<freq>]", "interval" |
Reporting periods; binned ranges. |
| SparseDtype | "Sparse" |
Mostly-empty indicator matrices. |
Dtype names and aliases come from the pandas user guide; the right-hand column is editorial guidance, not a pandas rule.
Strings: object versus str
The pandas documentation says strings can be held in two ways, object dtype or StringDtype, and recommends StringDtype; object dtype should be avoided to the extent possible. In pandas 3.x string columns show dtype str, and select_dtypes(include=[str]) now selects them, where earlier code used include=[object]. Code written for pandas 2.x that selects text columns with [object] can therefore miss string columns after an upgrade.
Mixed values and defaults
pd.Series([1, 2, 3, 4, 5, 6.0]) is float64, while pd.Series([1, 2, 3, 6.0, "foo"]) is object, so one stray text value turns a numeric column into object. Upcasting follows NumPy rules, and to_numpy() returns the lowest common dtype across columns.
Troubleshooting
ValueError when calling astype
An invalid conversion raises. On pandas 3.0.5, pd.Series(["4", "n/a"]).astype("int64") raises ValueError: invalid literal for int() with base 10: 'n/a'. Use pd.to_numeric(..., errors="coerce") first, inspect the resulting NaN rows, then cast to Int64 if you need integers.
Integer column became float
An operation that introduces NaN upcasts integer columns to float; for instance df[df > 0] on an integer frame returns float64 columns. Use a nullable integer dtype (Int64) when missing values are expected. Handling the missing rows themselves is covered in dropna in pandas.
The assigned dtype did not stick with loc
The documentation warns that dft.loc[:, ["a", "b"]] = dft.loc[:, ["a", "b"]].astype(np.uint8) keeps the original int64 dtype, because loc fits values into the existing dtype, whereas dft[["a", "b"]] = ... overwrites the columns and their dtype.
Naive to timezone-aware
Since pandas 2.0.0, astype from a naive datetime to a timezone-aware one raises; use Series.dt.tz_localize() instead.
The copy argument
The copy argument of astype is deprecated and ignored since pandas 3.0.0, which uses Copy-on-Write.
Free alternatives
pandas is itself free and open-source. These related free pieces of the Python stack are covered elsewhere on this site:
| Tool or task | Guide |
|---|---|
| NumPy arrays (one dtype per array) | NumPy sum, which shows how dtype affects results |
| Building a DataFrame from scratch | Create a DataFrame in Python |
FAQ
How do I check the dtype of a pandas column?
Use df.dtypes for all columns or df["col"].dtype for one.
How do I change a column’s dtype?
Use df["col"] = df["col"].astype("float64"), or df.astype({"col": "float64"}) for several columns at once. For text that may contain bad values, use pd.to_numeric with errors="coerce".
What does the object dtype mean?
It is the fallback for mixed or Python-object values, and historically for strings. The pandas documentation recommends StringDtype for text.
Should I keep ID codes as numbers?
This is editorial advice, not a pandas rule: store identifiers with leading zeros as strings, since they are labels rather than quantities.
Sources
- pandas user guide, Essential basic functionality, dtypes section: pandas.pydata.org/docs/user_guide/basics.html (read 2026-11-08).
- pandas API reference, DataFrame.astype: pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html (read 2026-11-08).
- Outputs described for the examples were produced by running the code on pandas 3.0.5 on 2026-11-08.







