Skip to main content

How to Load the California Housing Dataset in Python with scikit-learn

· 7 min read
Jagdish Kumawat
Founder @ Dewiride

The California Housing dataset is the classic dataset for learning regression: 20,640 districts, 8 numbers about each, and a house value to predict. scikit-learn downloads it for you with one function. This guide loads it as a pandas table, explains every column, shows where the download is kept, and points out the $500,000 cap that surprises people.

Syntax​

Syntax
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing(as_frame=False, return_X_y=False, data_home=None)
PartWhat it meansDefault
fetch_california_housing()Downloads the dataset the first time, then loads it from a cache folder
as_frame=TrueReturn pandas tables instead of NumPy arraysFalse
return_X_y=TrueReturn just the features and the target, as a pair, instead of one object with everythingFalse
data_home=Another folder for the cache~/scikit_learn_data

The result is a Bunch, a dictionary whose keys also work as attributes: housing.data holds the 8 features, housing.target the house values, and housing.feature_names the column names. With as_frame=True, housing.frame holds features and target together in one table.

Prerequisites​

Step 1: Load the Dataset​

Create load_housing.py:

load_housing.py
import pandas as pd
from sklearn.datasets import fetch_california_housing, get_data_home

pd.set_option("display.width", 120)

housing = fetch_california_housing(as_frame=True)
frame = housing.frame

print("Cached in:", get_data_home())
print("Rows and columns:", frame.shape)
print("Features:", housing.feature_names)
print("Target:", housing.target_names)
print()
print(frame.head())
print()
print(frame["MedHouseVal"].describe().round(3))
  • fetch_california_housing(as_frame=True) returns the data as pandas objects. .frame is one table with the 8 features and the target side by side.
  • get_data_home() returns the folder where scikit-learn keeps downloaded datasets.
  • pd.set_option("display.width", 120) lets pandas print the whole table on one line.

Run it:

Terminal
uv run python load_housing.py
Output
Cached in: /Users/you/scikit_learn_data
Rows and columns: (20640, 9)
Features: ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
Target: ['MedHouseVal']

MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
0 8.3252 41.0 6.984127 1.023810 322.0 2.555556 37.88 -122.23 4.526
1 8.3014 21.0 6.238137 0.971880 2401.0 2.109842 37.86 -122.22 3.585
2 7.2574 52.0 8.288136 1.073446 496.0 2.802260 37.85 -122.24 3.521
3 5.6431 52.0 5.817352 1.073059 558.0 2.547945 37.85 -122.25 3.413
4 3.8462 52.0 6.281853 1.081081 565.0 2.181467 37.85 -122.25 3.422

count 20640.000
mean 2.069
std 1.154
min 0.150
25% 1.196
50% 1.797
75% 2.647
max 5.000
Name: MedHouseVal, dtype: float64

A terminal showing the California Housing dataset loaded with scikit-learn: cached in the scikit_learn_data folder, 20640 rows and 9 columns, the 8 feature names, the first five rows of the table, and a summary of MedHouseVal with a mean of 2.069 and a maximum of 5.000.

Step 2: Understand the Columns​

The dataset describes itself in housing.DESCR. Its own words:

housing.DESCR (excerpt)
:Number of Instances: 20640

:Number of Attributes: 8 numeric, predictive attributes and the target

:Attribute Information:
- MedInc median income in block group
- HouseAge median house age in block group
- AveRooms average number of rooms per household
- AveBedrms average number of bedrooms per household
- Population block group population
- AveOccup average number of household members
- Latitude block group latitude
- Longitude block group longitude

:Missing Attribute Values: None

This dataset was obtained from the StatLib:
https://lib.stat.cmu.edu/datasets/houses.zip

The target variable is the median house value for California districts,
expressed in hundreds of thousands of dollars ($100,000).

This dataset was derived from the 1990 U.S. census, using one row per census
block group. A block group is the smallest geographical unit for which the U.S.
Census Bureau publishes sample data (a block group typically has a population
of 600 to 3,000 people).

So each row is one district (a census block group) in 1990, and the value to predict, MedHouseVal, is in hundreds of thousands of dollars: 4.526 means $452,600. Of the eight features, MedInc (median income) matters most: in How to Train a Random Forest Regression Model with scikit-learn it carries more than half of the forest's importance.

Step 3: Know About the Cap​

Look at the summary again: max 5.000. The exact maximum is 5.00001, and 965 districts, 4.7% of the data, share it. Values above $500,000 were all recorded as the same number, so a model can never learn how expensive those districts really are, and charts of its predictions show a column of points at 5.0. How to Plot Predicted vs Actual Values with Matplotlib shows what that looks like.

Where the Download Goes​

The first call downloads about 360 KB and saves it in scikit_learn_data in your home folder. Every later call reads that file, with no internet needed. If your program logs at INFO level, the first call prints:

Output (first call, with INFO logging)
INFO sklearn.datasets._california_housing: Downloading Cal. housing from https://ndownloader.figshare.com/files/5976036 to /Users/you/scikit_learn_data

scikit-learn's documentation explains how to move it: "By default the data directory is set to a folder named 'scikit_learn_data' in the user home folder. Alternatively, it can be set by the 'SCIKIT_LEARN_DATA' environment variable or programmatically by giving an explicit folder path." In code, that's fetch_california_housing(data_home="path/to/folder").

Common Mistakes​

MistakeWhat happensDo this instead
Forgetting as_frame=TrueYou get plain NumPy arrays without column namesPass as_frame=True and use .frame
Reading MedHouseVal as dollarsA value of 4.5 looks absurdMultiply by $100,000
Expecting values above $500,000The data stops at 5.0Treat 5.0 as "$500,000 or more"
Training on all 20,640 rowsYou have no fair way to measure the modelSplit first: How to Split Data into Training and Test Sets with scikit-learn

Troubleshooting​

SymptomLikely causeFix
ModuleNotFoundError: No module named 'sklearn'The script ran outside the project's environmentRun it with uv run: How to Run a Python Script with uv run
The table wraps across several linespandas' default width is narrowpd.set_option("display.width", 120)

FAQ​

Is the California Housing dataset free to use?​

It's distributed with scikit-learn's dataset loaders and comes from the StatLib archive. Check its source if you plan to redistribute the data itself.

Why 1990?​

It's the census the dataset was built from. It's ideal for learning, not for valuing a house today.

Can I load it without pandas?​

Yes: leave out as_frame=True and you get NumPy arrays in housing.data and housing.target.

Conclusion​

fetch_california_housing(as_frame=True).frame gave a 20,640 × 9 table: 8 numeric features per 1990 census district, and MedHouseVal, the median house value in units of $100,000, capped at 5.0. The download is cached in scikit_learn_data, so only the first call needs the internet.

Additional Resources​