Quick summary
Summarize this blog with AI
In pandas, a calculation can legitimately change a table into a Series or one scalar. If later code keeps indexing that result as if it were a row or table, you may see 'float' object is not subscriptable or a related NumPy scalar-indexing error. The fix is to match the next operation to the shape the previous operation actually returned.
These examples were tested with Python 3.12.14 and pandas 2.2.3 with Copy-on-Write enabled and pandas 3.0.6. Run the blocks in order. For non-pandas indexing, see the general float-indexing guide.
A Series mean is one number
import pandas as pd
scores = pd.DataFrame({
'team': ['A', 'A', 'B'],
'score': [10.0, 20.0, 30.0],
}, index=['row1', 'row2', 'row3'])
mean_score = float(scores['score'].mean())
print(mean_score)
try:
print(mean_score[0])
except TypeError as exc:
print(str(exc))
Expected output:
20.0
'float' object is not subscriptable
The explicit float conversion makes the error wording reproducible. Without it, pandas may return a NumPy scalar with different error wording. Both cases represent one value. Use mean_score directly when the next step needs the overall average.
Distinguish table, column, and cell selection
table = scores.loc[['row1'], ['score']]
column = scores['score']
cell = scores.at['row1', 'score']
print(table.shape)
print(column.shape)
print(float(cell))
print(scores.iloc[0]['score'])
Expected output:
(1, 1)
(3,)
10.0
10.0
Lists around both labels preserve a two-dimensional DataFrame. Selecting one named column returns a Series. at selects a single cell and is appropriate when you need a scalar. Do not append another [0] to that scalar. Use iloc for positions and loc for labels rather than depending on a Series index accidentally matching an integer position.
Keep a grouped result when one value per group is needed
team_means = scores.groupby('team')['score'].mean()
print(team_means.to_dict())
print(float(team_means.loc['A']))
scores['team_mean'] = scores.groupby('team')['score'].transform('mean')
print(scores['team_mean'].tolist())
print(len(scores))
Expected output:
{'A': 15.0, 'B': 30.0}
15.0
[15.0, 15.0, 30.0]
3
The grouped mean has one value per team. Transform repeats each team's result onto its original rows, preserving row count. Choose between those outputs before calculating. Converting a scalar to a one-element list after the fact does not recover missing team or row information.
An empty selection and a missing measurement are different
selected = scores.loc[scores['team'].eq('C'), 'score']
print(selected.empty)
if selected.empty:
print('No matching team')
missing = pd.Series([None, None], dtype='float64')
missing_mean = missing.mean()
print(pd.isna(missing_mean))
if pd.isna(missing_mean):
print('No observed score to average')
Expected output:
True
No matching team
True
No observed score to average
Neither case should automatically become zero. A missing mean is still a scalar, so indexing it again does not resolve the absence of observations. If missing values are skipped, report how many observations contributed to the result.
Make a one-row lookup contract explicit
def score_for_row(frame, label):
matches = frame.loc[frame.index == label, 'score']
if len(matches) != 1:
raise ValueError('expected exactly one matching row')
value = matches.iloc[0]
if pd.isna(value):
raise ValueError('matching row has a missing score')
return float(value)
print(score_for_row(scores, 'row2'))
try:
score_for_row(scores, 'absent')
except ValueError as exc:
print(str(exc))
Expected output:
20.0
expected exactly one matching row
The function rejects both no match and duplicate matching labels. A duplicate index can otherwise turn a label lookup into multiple results. This helper assumes a numeric score column; validate that schema at ingestion rather than sprinkling string casts through every calculation.
Inspect type(value), shape when available, and the exact indexing operation immediately before failure. Use a synthetic record instead of logging a complete private table. This page deliberately addresses pandas shape transitions; API payload shape mistakes have a separate diagnostic path.
Primary references: pandas indexing, Series.mean, and group transformations.