PythonMastery
reference 6 min read · lesson 18 of 25 in Reference

pandas Cheat Sheet

1 · The lesson

read

pandas works with tables of data, like a spreadsheet inside Python. A DataFrame is the whole table, and a Series is one column of it. This page is a quick reference for people who have used pandas a little. For the full tutorials, see pandas and pandas for data science.

Most pandas methods return a new table and leave the old one as it was. Keep that in mind as you read.

1. Create a Series and a DataFrame

A Series is a list of values with a label for each value. The labels are called the index.

python
import pandas as pd

s = pd.Series([3.5, 2.0], index=["tea", "milk"])
print(s["milk"])        # 2.0

df = pd.DataFrame({
    "name": ["Ada", "Grace", "Linus", "Hedy"],
    "team": ["A", "B", "A", "A"],
    "score": [90, 88, 75, 96],
})
print(df)
python
2.0
    name team  score
0    Ada    A     90
1  Grace    B     88
2  Linus    A     75
3   Hedy    A     96

Each key of the dict becomes a column. The numbers 0 to 3 on the left are the row labels (the index). You can also build a table from a list of dicts, one dict per row:

python
rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]
print(pd.DataFrame(rows).shape)    # (2, 2)
+ setup added so this can run · re-runs 1 earlier block on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

2. Read and save files

On your own computer you read a CSV file by its name. The first line of the file gives the column names.

python · run on your machine
df = pd.read_csv("scores.csv")
df = pd.read_csv("data.csv", sep=";", parse_dates=["day"])   # ";" separates the values; read "day" as dates
df.to_csv("out.csv", index=False)

index=False leaves out the 0, 1, 2 row labels when you save. To try read_csv() without a file, wrap some text in io.StringIO, which makes text act like a file:

python
import io

text = "name,score\nAda,90\nGrace,88"
small = pd.read_csv(io.StringIO(text))
print(small.shape)               # (2, 2)
print(small["score"].tolist())   # [90, 88]
+ setup added so this can run · re-runs 2 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

3. Look at the data

python
print(df.shape)                  # (4, 3)
print(df.columns.tolist())       # ['name', 'team', 'score']
print(df.head(2))
print(float(df["score"].mean())) # 87.25
+ setup added so this can run · re-runs 1 earlier block on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier
python
(4, 3)
['name', 'team', 'score']
    name team  score
0    Ada    A     90
1  Grace    B     88
87.25

df.head() shows the first 5 rows. df.info() lists the columns, their types, and how many values are missing. df.describe() gives the count, mean, min and max of each number column. df.shape is (rows, columns).

4. Select columns and rows

One column in square brackets gives a Series. A list of columns gives a smaller DataFrame.

To pick rows, there are two tools:

ToolPicks byExampleEnd of a slice
df.loc[...]the label of the row and the column namedf.loc[1, "name"]included
df.iloc[...]the position, counting from 0, like a listdf.iloc[0, 0]not included
python
print(df["name"].tolist())           # ['Ada', 'Grace', 'Linus', 'Hedy']
print(df[["name", "score"]].shape)   # (4, 2)
print(df.loc[1, "name"])             # Grace
print(df.iloc[0, 0])                 # Ada
print(df.loc[0:2, "name"].tolist())  # ['Ada', 'Grace', 'Linus']
print(df.iloc[0:2, 0].tolist())      # ['Ada', 'Grace']
+ setup added so this can run · re-runs 2 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

5. Filter rows

A test on a column gives one True or False per row. Put the test inside df[...] to keep only the rows where it is True. To join two tests, use & for "and" and | for "or", and put brackets around each test.

python
print(df[df["score"] > 85]["name"].tolist())                        # ['Ada', 'Grace', 'Hedy']
print(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # ['Ada', 'Hedy']
print(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # ['Ada', 'Linus']
print(df.query("score > 89")["name"].tolist())                      # ['Ada', 'Hedy']
+ setup added so this can run · re-runs 3 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

6. Add and change columns

python
import pandas as pd

df = pd.DataFrame({
    "name": ["Ada", "Grace", "Linus", "Hedy"],
    "team": ["A", "B", "A", "A"],
    "score": [90, 88, 75, 96],
})
df["pct"] = df["score"] / 100
print(df["pct"].tolist())                  # [0.9, 0.88, 0.75, 0.96]

df.loc[df["score"] < 80, "bonus"] = 5      # set bonus only where score < 80
print(df["bonus"].tolist())                # [nan, nan, 5.0, nan]

print(df.rename(columns={"score": "pts"}).columns.tolist())  # ['name', 'team', 'pts', 'pct', 'bonus']
df = df.drop(columns=["pct", "bonus"])
print(df.columns.tolist())                 # ['name', 'team', 'score']

The rows that did not match get NaN, which means "no value". rename() and drop() return a new table, so assign the result if you want to keep it.

7. Sort

python
print(df.sort_values("score", ascending=False)["name"].tolist())  # ['Hedy', 'Ada', 'Grace', 'Linus']
print(df.nlargest(2, "score")["name"].tolist())                   # ['Hedy', 'Ada']
print(df.sort_values(["team", "score"])["name"].tolist())         # ['Linus', 'Ada', 'Hedy', 'Grace']
+ setup added so this can run · re-runs 4 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

The last line sorts by team first, then by score inside each team.

8. Group and count

groupby() splits the rows into groups that share a value, then works out one result per group.

python
print(df.groupby("team")["score"].mean().to_dict())    # {'A': 87.0, 'B': 88.0}
print(df.groupby("team")["score"].agg(["min", "max"]))
print(df["team"].value_counts().to_dict())             # {'A': 3, 'B': 1}
+ setup added so this can run · re-runs 5 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier
python
{'A': 87.0, 'B': 88.0}
      min  max
team          
A      75   96
B      88   88
{'A': 3, 'B': 1}

9. Missing values

pandas shows a missing value as NaN.

python
s = pd.Series([4.0, None, 2.5])
print(s.isna().tolist())       # [False, True, False]
print(int(s.isna().sum()))     # 1
print(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]
print(s.dropna().tolist())     # [4.0, 2.5]
print(float(s.mean()))         # 3.25
+ setup added so this can run · re-runs 3 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

mean() and sum() skip missing values. On a DataFrame, df.dropna() drops every row that has a gap.

10. Combine tables

merge() joins two tables on a shared column, like a JOIN in SQL. pd.concat() puts one table under another.

python
cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})

print(df.merge(cities, on="name")["city"].tolist())               # ['London', 'Vienna']
print(df.merge(cities, on="name", how="left")["city"].tolist())   # ['London', nan, nan, 'Vienna']
print(len(pd.concat([df, df])))                                    # 8
+ setup added so this can run · re-runs 9 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

pd = _AutoMock('pd')
df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

By default, merge() keeps only the rows that match in both tables. how="left" keeps every row of df, and a row with no match gets NaN.

11. Run a function on a column

python
print(df["name"].apply(len).tolist())       # [3, 5, 5, 4]
print(df["score"].apply(lambda x: "pass" if x >= 80 else "fail").tolist())  # ['pass', 'pass', 'fail', 'pass']
print(df["name"].str.upper().tolist())      # ['ADA', 'GRACE', 'LINUS', 'HEDY']
+ setup added so this can run · re-runs 10 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')
pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
    'cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})\n\nprint(df.merge(cities, on="name")["city"].tolist())               # [\'London\', \'Vienna\']\nprint(df.merge(cities, on="name", how="left")["city"].tolist())   # [\'London\', nan, nan, \'Vienna\']\nprint(len(pd.concat([df, df])))                                    # 8',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

apply() calls your function once for each value. .str gives you string methods for a whole column at once.

Common mistakes

Changing a filtered copy. df[df["score"] > 80]["bonus"] = 1 first makes a filtered table, then changes that table, not df. pandas shows a SettingWithCopyWarning. Do the filter and the change in one loc:

python
import pandas as pd

df = pd.DataFrame({
    "name": ["Ada", "Grace", "Linus", "Hedy"],
    "team": ["A", "B", "A", "A"],
    "score": [90, 88, 75, 96],
})
df.loc[df["score"] > 80, "bonus"] = 1
print(df["bonus"].tolist())    # [1.0, 1.0, nan, 1.0]
df = df.drop(columns=["bonus"])

and / or instead of & / |. df["score"] > 80 and df["score"] < 95 raises a ValueError ("truth value of a Series is ambiguous"). Use & or |, and put brackets around each test, because & is worked out before >:

python
print(df[(df["score"] > 80) & (df["score"] < 95)]["name"].tolist())   # ['Ada', 'Grace']
+ setup added so this can run · re-runs 12 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')
pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
    'cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})\n\nprint(df.merge(cities, on="name")["city"].tolist())               # [\'London\', \'Vienna\']\nprint(df.merge(cities, on="name", how="left")["city"].tolist())   # [\'London\', nan, nan, \'Vienna\']\nprint(len(pd.concat([df, df])))                                    # 8',
    'print(df["name"].apply(len).tolist())       # [3, 5, 5, 4]\nprint(df["score"].apply(lambda x: "pass" if x >= 80 else "fail").tolist())  # [\'pass\', \'pass\', \'fail\', \'pass\']\nprint(df["name"].str.upper().tolist())      # [\'ADA\', \'GRACE\', \'LINUS\', \'HEDY\']',
    'import pandas as pd\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\ndf.loc[df["score"] > 80, "bonus"] = 1\nprint(df["bonus"].tolist())    # [1.0, 1.0, nan, 1.0]\ndf = df.drop(columns=["bonus"])',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

loc includes the end label, iloc does not.

python
print(len(df.loc[0:2]), len(df.iloc[0:2]))    # 3 2
+ setup added so this can run · re-runs 13 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')
pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
    'cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})\n\nprint(df.merge(cities, on="name")["city"].tolist())               # [\'London\', \'Vienna\']\nprint(df.merge(cities, on="name", how="left")["city"].tolist())   # [\'London\', nan, nan, \'Vienna\']\nprint(len(pd.concat([df, df])))                                    # 8',
    'print(df["name"].apply(len).tolist())       # [3, 5, 5, 4]\nprint(df["score"].apply(lambda x: "pass" if x >= 80 else "fail").tolist())  # [\'pass\', \'pass\', \'fail\', \'pass\']\nprint(df["name"].str.upper().tolist())      # [\'ADA\', \'GRACE\', \'LINUS\', \'HEDY\']',
    'import pandas as pd\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\ndf.loc[df["score"] > 80, "bonus"] = 1\nprint(df["bonus"].tolist())    # [1.0, 1.0, nan, 1.0]\ndf = df.drop(columns=["bonus"])',
    'print(df[(df["score"] > 80) & (df["score"] < 95)]["name"].tolist())   # [\'Ada\', \'Grace\']',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

inplace=True returns None. df = df.sort_values("score", inplace=True) sets df to None. Either assign the result, or use inplace=True without assigning. Assigning is clearer:

python
df_sorted = df.sort_values("score")
print(df_sorted["name"].tolist())    # ['Linus', 'Grace', 'Ada', 'Hedy']
+ setup added so this can run · re-runs 13 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

df = _AutoMock('df')
pd = _AutoMock('pd')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
    'cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})\n\nprint(df.merge(cities, on="name")["city"].tolist())               # [\'London\', \'Vienna\']\nprint(df.merge(cities, on="name", how="left")["city"].tolist())   # [\'London\', nan, nan, \'Vienna\']\nprint(len(pd.concat([df, df])))                                    # 8',
    'print(df["name"].apply(len).tolist())       # [3, 5, 5, 4]\nprint(df["score"].apply(lambda x: "pass" if x >= 80 else "fail").tolist())  # [\'pass\', \'pass\', \'fail\', \'pass\']\nprint(df["name"].str.upper().tolist())      # [\'ADA\', \'GRACE\', \'LINUS\', \'HEDY\']',
    'import pandas as pd\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\ndf.loc[df["score"] > 80, "bonus"] = 1\nprint(df["bonus"].tolist())    # [1.0, 1.0, nan, 1.0]\ndf = df.drop(columns=["bonus"])',
    'print(df[(df["score"] > 80) & (df["score"] < 95)]["name"].tolist())   # [\'Ada\', \'Grace\']',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

df.append() is gone. It was removed in pandas 2.0, so it raises an AttributeError. Use pd.concat():

python
new_row = pd.DataFrame([{"name": "Margaret", "team": "B", "score": 91}])
df = pd.concat([df, new_row], ignore_index=True)
print(df.shape)    # (5, 3)
+ setup added so this can run · re-runs 11 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

pd = _AutoMock('pd')
df = _AutoMock('df')

# Earlier blocks on this page that this one builds on, re-run quietly first.
try:
    import pandas as pd
    import io
except Exception:
    pass
_pm_earlier = [
    'import pandas as pd\n\ns = pd.Series([3.5, 2.0], index=["tea", "milk"])\nprint(s["milk"])        # 2.0\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\nprint(df)',
    'rows = [{"name": "Ada", "score": 90}, {"name": "Hedy", "score": 96}]\nprint(pd.DataFrame(rows).shape)    # (2, 2)',
    'import io\n\ntext = "name,score\\nAda,90\\nGrace,88"\nsmall = pd.read_csv(io.StringIO(text))\nprint(small.shape)               # (2, 2)\nprint(small["score"].tolist())   # [90, 88]',
    'print(df.shape)                  # (4, 3)\nprint(df.columns.tolist())       # [\'name\', \'team\', \'score\']\nprint(df.head(2))\nprint(float(df["score"].mean())) # 87.25',
    'print(df["name"].tolist())           # [\'Ada\', \'Grace\', \'Linus\', \'Hedy\']\nprint(df[["name", "score"]].shape)   # (4, 2)\nprint(df.loc[1, "name"])             # Grace\nprint(df.iloc[0, 0])                 # Ada\nprint(df.loc[0:2, "name"].tolist())  # [\'Ada\', \'Grace\', \'Linus\']\nprint(df.iloc[0:2, 0].tolist())      # [\'Ada\', \'Grace\']',
    'print(df[df["score"] > 85]["name"].tolist())                        # [\'Ada\', \'Grace\', \'Hedy\']\nprint(df[(df["team"] == "A") & (df["score"] > 80)]["name"].tolist()) # [\'Ada\', \'Hedy\']\nprint(df[df["name"].isin(["Ada", "Linus"])]["name"].tolist())       # [\'Ada\', \'Linus\']\nprint(df.query("score > 89")["name"].tolist())                      # [\'Ada\', \'Hedy\']',
    'print(df.sort_values("score", ascending=False)["name"].tolist())  # [\'Hedy\', \'Ada\', \'Grace\', \'Linus\']\nprint(df.nlargest(2, "score")["name"].tolist())                   # [\'Hedy\', \'Ada\']\nprint(df.sort_values(["team", "score"])["name"].tolist())         # [\'Linus\', \'Ada\', \'Hedy\', \'Grace\']',
    'print(df.groupby("team")["score"].mean().to_dict())    # {\'A\': 87.0, \'B\': 88.0}\nprint(df.groupby("team")["score"].agg(["min", "max"]))\nprint(df["team"].value_counts().to_dict())             # {\'A\': 3, \'B\': 1}',
    's = pd.Series([4.0, None, 2.5])\nprint(s.isna().tolist())       # [False, True, False]\nprint(int(s.isna().sum()))     # 1\nprint(s.fillna(0).tolist())    # [4.0, 0.0, 2.5]\nprint(s.dropna().tolist())     # [4.0, 2.5]\nprint(float(s.mean()))         # 3.25',
    'cities = pd.DataFrame({"name": ["Ada", "Hedy"], "city": ["London", "Vienna"]})\n\nprint(df.merge(cities, on="name")["city"].tolist())               # [\'London\', \'Vienna\']\nprint(df.merge(cities, on="name", how="left")["city"].tolist())   # [\'London\', nan, nan, \'Vienna\']\nprint(len(pd.concat([df, df])))                                    # 8',
    'import pandas as pd\n\ndf = pd.DataFrame({\n    "name": ["Ada", "Grace", "Linus", "Hedy"],\n    "team": ["A", "B", "A", "A"],\n    "score": [90, 88, 75, 96],\n})\ndf.loc[df["score"] > 80, "bonus"] = 1\nprint(df["bonus"].tolist())    # [1.0, 1.0, nan, 1.0]\ndf = df.drop(columns=["bonus"])',
]
def _pm_run_earlier(_srcs, _g):
    import sys as _s, io as _io, warnings as _w
    for _src in _srcs:
        _o, _e = _s.stdout, _s.stderr
        _s.stdout = _s.stderr = _io.StringIO()
        try:
            with _w.catch_warnings():
                _w.simplefilter('ignore')
                exec(compile(_src, '<earlier block>', 'exec'), _g)
        except (Exception, SystemExit):
            pass
        finally:
            _s.stdout, _s.stderr = _o, _e
    if 'matplotlib.pyplot' in _s.modules:
        _s.modules['matplotlib.pyplot'].close('all')   # their plots belong to their own blocks
_pm_run_earlier(_pm_earlier, globals())
del _pm_earlier, _pm_run_earlier

Column names are case-sensitive. df["Score"] raises a KeyError when the column is called score. Check the exact names with df.columns.tolist().

Found this useful? Share it with a friend who’s learning Python.