Have you ever asked Pandas for the average of a data frame and been told it can't be done?
weather = pd.DataFrame({'country': ['Norway', 'Norway', 'Peru'],
'city': ['Oslo', 'Bergen', 'Lima'],
'temp': [5.0, 8.0, 18.0]})
weather.mean()
TypeError: Cannot perform reduction 'mean' with string dtype
The short answer is that the data frame includes text columns, and there's no such thing as the mean of "Oslo" and "Bergen." Tell Pandas to skip them:
weather.mean(numeric_only=True)
temp 10.333333
dtype: float64
The same message, with 'median' or 'std' in place of 'mean', has the same cause and the same fix.
The groupby version says it differently
If you hit this while grouping, you'll see a different message:
weather.groupby('country').mean()
TypeError: dtype 'str' does not support operation 'mean'
It's the same problem, since groupby tries to average every column except the one you grouped by, and that includes city. resample and pivot_table go through the same machinery and produce the same wording.
numeric_only=True works here too, but in a groupby, I'd rather name the column I want:
weather.groupby('country')['temp'].mean()
country
Norway 6.5
Peru 18.0
Name: temp, dtype: float64
This is not just a workaround. Selecting the column says what question you're asking, it doesn't break when someone adds a column to the source data next month, and it doesn't waste time computing results you'll throw away. If you want different summaries for different columns, agg with named aggregations says all of it in one place:
weather.groupby('country').agg(temp=('temp', 'mean'),
cities=('city', 'count'))
temp cities
country
Norway 6.5 2
Peru 18.0 1
Why sum works when mean does not
You might reasonably wonder why this fails when sum does not:
weather.sum()
country NorwayNorwayPeru
city OsloBergenLima
temp 31.0
dtype: object
Adding strings in Python concatenates them, so a "sum" of text is defined, even if it's rarely useful. min and max work too, and give you alphabetical order. A mean requires dividing by a count, and a string can't be divided, so Pandas stops.
This also explains the older error messages you may find in search results. Pandas 2 attempted the sum first, and then failed trying to convert the glued-together text into a number, with a message like Could not convert ['NorwayNorwayPeru' 'OsloBergenLima'] to numeric. That's the text of both string columns, glued together. Pandas 3 knows the column is text before it starts, and says so.
When the numbers are text
The frustrating version of this error is on a column that obviously contains numbers:
sales = pd.read_csv(io.StringIO('region,revenue\nNorth,"$1,200"\nSouth,$850\n'))
sales['revenue'].mean()
TypeError: Cannot perform reduction 'mean' with string dtype
Check the dtypes:
sales.dtypes
region str
revenue str
dtype: object
The dollar signs and thousands separators made read_csv treat revenue as text. numeric_only=True would silently skip the column you care about, so here the fix is to clean the text and convert it:
sales['revenue'].str.replace(r'[$,]', '', regex=True).astype(float).mean()
np.float64(1025.0)
When a column you expected to be numeric shows up as str, look for currency symbols, commas, percent signs, footnote markers, and placeholders like "n/a". Real-world data sources are full of them. For thousands separators alone, read_csv(..., thousands=',') handles it at load time.
Practice
See mean in Pandas and groupby in Pandas for averages on real data, and to_numeric in Pandas for cleaning numbers stored as text. Then try the groupby exercise.