Mathew K Analytics

Lesson 2 · Pandas Full Course

Install Pandas the Right Way and Fix Setup Errors for Good | Pandas Course #2

In this lesson you'll be able to: Check which Python and pandas versions you are running Install, upgrade and verify pandas and its helper packages Point…

What you'll learn

Datasets used in this lesson

Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.

📓 Full notebook

Download .ipynb

Pandas 02: Installing Pandas and Setting Up the Environment#

In this lesson you'll be able to:

  • Check which Python and pandas versions you are running
  • Install, upgrade and verify pandas and its helper packages
  • Point pandas at your data files without path errors
  • Tune display options and make results repeatable Data: the Titanic list, then every file in data/pandas

Warm-up: is everything still working?#

Lesson 01 loaded the Titanic list and grouped it by class.

import pandas as pd

df = pd.read_csv("data/pandas/titanic.csv")
print(df.shape)
df.groupby("Pclass")["Survived"].mean().round(2)
(891, 12)
Pclass
1    0.63
2    0.47
3    0.24
Name: Survived, dtype: float64

Check what you have: Python and pandas versions#

Most setup problems are version problems. Check before you install.

import platform

print("Python", platform.python_version())
print("pandas", pd.__version__)
ver = tuple(int(p) for p in pd.__version__.split(".")[:2])
print("pandas 2.2 or newer:", ver >= (2, 2))
Python 3.12.1
pandas 3.0.6
pandas 2.2 or newer: True
from importlib.metadata import version

core = ["numpy", "matplotlib", "seaborn"]
for name in core:
    print(name, version(name))
numpy 2.5.4
matplotlib 3.11.2
seaborn 0.13.2

Quick check: is this pandas 2 or newer?

major = int(pd.__version__.split(".")[0])
print("major version at least 2:", major >= 2)
major version at least 2: True

Why not just compare the text, like "10.0" > "2.0"?

print("10.0" > "2.0")
print(10 > 2)
False
True

Why the version matters#

pandas 2 and 3 changed defaults: text type, copy rules, old APIs. Code from old tutorials may warn or fail. Match your version.

print(df["Name"].dtype)
print(df["Name"].str.len().max())
str
82

Install, upgrade and verify#

Run these in a terminal, not inside the notebook: python -m pip install --upgrade pandas or conda install pandas

Optional extras#

Excel needs openpyxl, fast file formats need pyarrow.

from importlib.util import find_spec

extras = ["openpyxl", "pyarrow", "sklearn", "plotly"]
for name in extras:
    found = find_spec(name) is not None
    print(f"{name:<10} {found}")
openpyxl   True
pyarrow    True
sklearn    True
plotly     True

Common mistake: importing panda instead of pandas

import panda as pd
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[9], line 1
----> 1 import panda as pd

ModuleNotFoundError: No module named 'panda'
import pandas as pd
print("pandas", pd.__version__, "is ready")
pandas 3.0.6 is ready

Your turn: is seaborn importable, and which version is it?

print(find_spec("seaborn") is not None)
import seaborn as sns
print(sns.__version__)
True
0.13.2

Tip: if pandas itself is missing, the error is the same. Install it into the Python your notebook uses: %pip install pandas

Where to write your code#

Jupyter: run jupyter lab in a terminal, then open a notebook. Each cell runs on its own and keeps its results for the next.

Find your files: the working folder and relative paths#

Relative paths start from the folder your code runs in.

from pathlib import Path

data_dir = Path("data") / "pandas"
print(data_dir, data_dir.exists())
data\pandas True
files = sorted(p.name for p in data_dir.glob("*.csv*"))
print("titanic.csv" in files, "penguins.csv" in files)
True True
titanic_path = data_dir / "titanic.csv"
print(titanic_path.name)
print(titanic_path.stem, titanic_path.suffix)
print(titanic_path.parent.name)
titanic.csv
titanic .csv
pandas

Common mistake: a path that skips a folder

path = "pandas/titanic.csv"
pd.read_csv(path)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[15], line 2
      1 path = "pandas/titanic.csv"
----> 2 pd.read_csv(path)

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\io\parsers\readers.py:872, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, skip_blank_lines, parse_dates, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, low_memory, memory_map, float_precision, storage_options, dtype_backend)
    860 kwds_defaults = _refine_defaults_read(
    861     dialect,
    862     delimiter,
   (...)
    868     dtype_backend=dtype_backend,
    869 )
    870 kwds.update(kwds_defaults)
--> 872 return _read(filepath_or_buffer, kwds)

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\io\parsers\readers.py:300, in _read(filepath_or_buffer, kwds)
    297 _validate_names(kwds.get("names", None))
    299 # Create the parser.
--> 300 parser = TextFileReader(filepath_or_buffer, **kwds)
    302 if chunksize or iterator:
    303     return parser

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\io\parsers\readers.py:1643, in TextFileReader.__init__(self, f, engine, **kwds)
   1640     self.options["has_index_names"] = kwds["has_index_names"]
   1642 self.handles: IOHandles | None = None
-> 1643 self._engine = self._make_engine(f, self.engine)

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\io\parsers\readers.py:1907, in TextFileReader._make_engine(self, f, engine)
   1905     if "b" not in mode:
   1906         mode += "b"
-> 1907 self.handles = get_handle(
   1908     f,
   1909     mode,
   1910     encoding=self.options.get("encoding", None),
   1911     compression=self.options.get("compression", None),
   1912     memory_map=self.options.get("memory_map", False),
   1913     is_text=is_text,
   1914     errors=self.options.get("encoding_errors", "strict"),
   1915     storage_options=self.options.get("storage_options", None),
   1916 )
   1917 assert self.handles is not None
   1918 f = self.handles.handle

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\io\common.py:930, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)
    925 elif isinstance(handle, str):
    926     # Check whether the filename is to be opened in binary mode.
    927     # Binary mode does not support 'encoding' and 'newline'.
    928     if ioargs.encoding and "b" not in ioargs.mode:
    929         # Encoding
--> 930         handle = open(
    931             handle,
    932             ioargs.mode,
    933             encoding=ioargs.encoding,
    934             errors=errors,
    935             newline="",
    936         )
    937     else:
    938         # Binary mode
    939         handle = open(handle, ioargs.mode)

FileNotFoundError: [Errno 2] No such file or directory: 'pandas/titanic.csv'
path = data_dir / "titanic.csv"
print(path.exists())
pd.read_csv(path).shape
True
(891, 12)
retail_path = data_dir / "online_retail.csv.gz"
peek = pd.read_csv(retail_path, nrows=3)
peek[["InvoiceNo", "Description", "Quantity", "Country"]]
InvoiceNo Description Quantity Country
0 536365 WHITE HANGING HEART T-LIGHT HOLDER 6 United Kingdom
1 536365 WHITE METAL LANTERN 6 United Kingdom
2 536365 CREAM CUPID HEARTS COAT HANGER 8 United Kingdom

Quick check: can we catch a typo before read_csv crashes?

guess = data_dir / "titanc.csv"
if guess.exists():
    print(pd.read_csv(guess).shape)
else:
    print("Not found:", guess.name)
Not found: titanc.csv
cols = ["Name", "Sex", "Age", "Survived"]
slim = pd.read_csv(titanic_path, usecols=cols)
print(slim.shape)
print(slim.memory_usage(deep=True).sum() < df.memory_usage(deep=True).sum())
(891, 4)
True

Your turn: does data/pandas/penguins.csv exist? How many rows?

peng_path = data_dir / "penguins.csv"
print(peng_path.exists())
print(len(pd.read_csv(peng_path)), "penguins")
True
344 penguins

Make output readable: display options#

Options set how many rows, columns and decimals you see.

for opt in ["max_rows", "max_columns", "precision"]:
    print(opt, pd.get_option("display." + opt))
max_rows 60
max_columns 20
precision 6
pd.set_option("display.precision", 2)
df[["Age", "Fare"]].describe()
Age Fare
count 714.00 891.00
mean 29.70 32.20
std 14.53 49.69
min 0.42 0.00
25% 20.12 7.91
50% 28.00 14.45
75% 38.00 31.00
max 80.00 512.33
with pd.option_context("display.max_rows", 6):
    print(df["Name"].head(10))
print(pd.get_option("display.max_rows"))
0                              Braund, Mr. Owen Harris
1    Cumings, Mrs. John Bradley (Florence Briggs Th...
2                               Heikkinen, Miss. Laina
                           ...                        
7                       Palsson, Master. Gosta Leonard
8    Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)
9                  Nasser, Mrs. Nicholas (Adele Achem)
Name: Name, Length: 10, dtype: str
60
with pd.option_context("display.max_colwidth", 20):
    print(df["Name"].head(3))
0    Braund, Mr. Owen...
1    Cumings, Mrs. Jo...
2    Heikkinen, Miss....
Name: Name, dtype: str
totals = df.groupby("Pclass")["Fare"].sum()
with pd.option_context("display.float_format", "{:,.2f}".format):
    print(totals)
Pclass
1   18,177.41
2    3,801.84
3    6,714.70
Name: Fare, dtype: float64

Common mistake: a misspelt option name

pd.set_option("display.precison", 2)
---------------------------------------------------------------------------
OptionError                               Traceback (most recent call last)
Cell In[26], line 1
----> 1 pd.set_option("display.precison", 2)

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\_config\config.py:277, in set_option(*args)
    274     raise ValueError("Must provide an even number of non-keyword arguments")
    276 for k, v in zip(args[::2], args[1::2], strict=True):
--> 277     key = _get_single_key(k)
    279     opt = _get_registered_option(key)
    280     if opt and opt.validator:

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\pandas\_config\config.py:131, in _get_single_key(pat)
    129 if len(keys) == 0:
    130     _warn_if_deprecated(pat)
--> 131     raise OptionError(f"No such keys(s): {pat!r}")
    132 if len(keys) > 1:
    133     raise OptionError("Pattern matched multiple keys")

OptionError: No such keys(s): 'display.precison'
pd.set_option("display.precision", 3)
print(pd.get_option("display.precision"))
3

Your turn: show describe() of Fare with 1 decimal place, temporarily.

with pd.option_context("display.precision", 1):
    print(df["Fare"].describe())
count    891.0
mean      32.2
std       49.7
min        0.0
25%        7.9
50%       14.5
75%       31.0
max      512.3
Name: Fare, dtype: float64
pd.reset_option("display.precision")
print(pd.get_option("display.precision"))
6

Make your work repeatable#

Fix random seeds, save outputs to one folder, record versions.

a = df.sample(3, random_state=1)
b = df.sample(3, random_state=2)
print(a["PassengerId"].tolist(), b["PassengerId"].tolist())
[863, 224, 85] [708, 38, 616]
first = df.sample(3, random_state=42)
print(first[["PassengerId", "Name", "Pclass"]])
     PassengerId                                               Name  Pclass
709          710  Moubarek, Master. Halim Gonios ("William George")       3
439          440             Kvillner, Mr. Johan Henrik Johannesson       2
840          841                        Alhomaki, Mr. Ilmari Rudolf       3

Quick check: run it again with random_state=42. Same passengers?

b = df.sample(3, random_state=42)
print(b["PassengerId"].tolist(), first.equals(b))
[710, 440, 841] True
import os

os.makedirs("output/pandas", exist_ok=True)
libs = ["pandas", "numpy", "matplotlib", "seaborn"]
rows = [{"package": n, "version": version(n)} for n in libs]
versions = pd.DataFrame(rows)
versions
package version
0 pandas 3.0.6
1 numpy 2.5.4
2 matplotlib 3.11.2
3 seaborn 0.13.2

Common mistake: asking for sklearn by its import name

version("sklearn")
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\importlib\metadata\__init__.py:397, in Distribution.from_name(cls, name)
    396 try:
--> 397     return next(cls.discover(name=name))
    398 except StopIteration:

StopIteration: 

During handling of the above exception, another exception occurred:

PackageNotFoundError                      Traceback (most recent call last)
Cell In[34], line 1
----> 1 version("sklearn")

File ~\AppData\Local\Programs\Python\Python312\Lib\importlib\metadata\__init__.py:888, in version(distribution_name)
    881 def version(distribution_name):
    882     """Get the version string for the named package.
    883 
    884     :param distribution_name: The name of the distribution package to query.
    885     :return: The version string for the package as defined in the package's
    886         "Version" metadata key.
    887     """
--> 888     return distribution(distribution_name).version

File ~\AppData\Local\Programs\Python\Python312\Lib\importlib\metadata\__init__.py:861, in distribution(distribution_name)
    855 def distribution(distribution_name):
    856     """Get the ``Distribution`` instance for the named package.
    857 
    858     :param distribution_name: The name of the distribution package as a string.
    859     :return: A ``Distribution`` instance (or subclass thereof).
    860     """
--> 861     return Distribution.from_name(distribution_name)

File ~\AppData\Local\Programs\Python\Python312\Lib\importlib\metadata\__init__.py:399, in Distribution.from_name(cls, name)
    397     return next(cls.discover(name=name))
    398 except StopIteration:
--> 399     raise PackageNotFoundError(name)

PackageNotFoundError: No package metadata was found for sklearn
print(version("scikit-learn"))
1.9.1
ver_path = "output/pandas/l02_versions.csv"
versions.to_csv(ver_path, index=False)
pd.read_csv(ver_path)
package version
0 pandas 3.0.6
1 numpy 2.5.4
2 matplotlib 3.11.2
3 seaborn 0.13.2

Mini-project: health check every dataset#

Can this setup load all the files the series needs?

report = []
for f in sorted(data_dir.glob("*.csv*")):
    d = pd.read_csv(f, low_memory=False)
    report.append({"file": f.name, "rows": len(d),
                   "cols": d.shape[1],
                   "missing": int(d.isna().sum().sum())})
health = pd.DataFrame(report)
print(len(health), "files loaded")
16 files loaded
health.sort_values("rows", ascending=False).head(5)
file rows cols missing
8 online_retail.csv.gz 541909 8 136534
1 diamonds.csv 53940 10 0
10 salary_survey.csv 26232 18 81000
4 housing.csv 20640 10 207
12 superstore.csv 8399 21 63
import matplotlib.pyplot as plt

sizes = health.set_index("file")["rows"].sort_values()
ax = sizes.plot(kind="barh", logx=True, color="steelblue")
ax.set_title("Rows in each dataset")
ax.set_xlabel("Rows (log scale)")
ax.set_ylabel("File")
plt.show()
No description has been provided for this image
complete = health[health["missing"] == 0]
print(complete["file"].tolist())
['aapl.csv', 'diamonds.csv', 'flights.csv', 'gapminder.csv', 'iris.csv', 'stocks.csv', 'tips.csv']
cells = health["rows"] * health["cols"]
health["pct_missing"] = (health["missing"] / cells * 100).round(1)
health.sort_values("pct_missing", ascending=False).head(4)
file rows cols missing pct_missing
10 salary_survey.csv 26232 18 81000 17.2
15 titanic.csv 891 12 866 8.1
7 netflix_titles.csv 7787 12 3631 3.9
8 online_retail.csv.gz 541909 8 136534 3.1
health.loc[health["file"] == "titanic.csv"]
file rows cols missing pct_missing
15 titanic.csv 891 12 866 8.1
health_path = "output/pandas/l02_data_health.csv"
health.to_csv(health_path, index=False)
pd.read_csv(health_path).equals(health)
True

Finding: every file loads, from flights (144 rows) to online retail (541,909). Diamonds and iris are complete; others have gaps to clean later.

Recap#

  • pd.__version__ and importlib.metadata report versions
  • Install or upgrade in a terminal with pip or conda
  • ModuleNotFoundError means a misspelt or missing package
  • Build paths with pathlib and check them with .exists()
  • Use option_context, random_state and an output folder

Challenges#

  1. Add a mb column to the health report using memory_usage.
  2. Set display.max_columns to 5 and show the superstore head.
  3. Add scikit-learn and pyarrow to the saved versions file.

What's next#

Lesson 03: Understanding Series and DataFrames. What a Series is, how DataFrames hold them, and why labels matter.

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.