Matterhorn pandas

· Manuel Z

Matterhorn summit window from 50 years of historical weather + pandas.

Matterhorn
Matterhorn (credit Caramelized Onions)

1. Background #

I have been thinking about Matterhorn for a long, long time and this may be the year when it happens. Wish me luck!

There are more than a dozen options to climb Matterhorn, and the "normal routes" on the Italian and Swiss side are probably the easiest. Of these, the Hörnli Ridge on the Swiss side (although crowded) has the simplest logistics and easy access from the resort village of Zermatt. This!

The totally awesome Hörnli Hut sits at its base.

Matterhorn is one of the highest peaks in Europe at 4,478m (14,692ft). Reduced oxygen at high altitude is totally a thing and acclimatization seems like a good idea.

Weather is the main variable: you don't want to be caught in a storm on your way down. Rain makes the rock slippery and snow, especially fresh snow, makes the climb a lot more complicated.

2. Plan #

Go solo (some climbers use a guide) and spend 5 days (4 nights) in Switzerland, with a 3-day summit window:

Unless you plan to bum around Europe for a couple of weeks (I don't :) waiting for a window of good weather and last minute availability at the hut, you need to commit to flights, book the hut ahead of time and hope for the best.

That leaves two questions:

3. Conventional wisdom #

The Hörnli Hut is open between the end of June and mid-September each year. This is a clue.

The optimal summit window is probably mid-July to mid-September: snow before and after that, with likely variations between years. I watched many hours of Matterhorn climbing videos on YouTube:

The recommended summit ascent starts early: 4:30AM ("alpine start"), aiming for a 4-5h ascent and similar descent: be back at the hut by 2PM, beat afternoon showers (convective storms) and make it to the last gondola download from Schwarzsee (between 4:30-5PM). Guides are reportedly very strict with their clients about a 9AM summit cut-off and moving fast throughout.

It would be nice to get historical weather averages for snow, temperature, precipitation (incl. afternoon showers) and pick a good 3-day summit window between July and September.

4. Weather #

The first thing I found is the MeteoSwiss weather forecast.

I have been comparing it (cloud, precipitation) with actual weather conditions on Matterhorn from the Hörnli Hut webcam. It seems pretty accurate. The 8-day forecast (Error band for temperature. Nice!) should be good enough to decide on the best summit day once I'm in Switzerland.

Looking for historical weather, I found Open Meteo. Historical Weather API. JSON. Open Source ❤️. Awesome!

Download 50 years of historical weather for Matterhorn (click)
# Craft your own query that looks like
# this (438,312 data points; 19MB).
# Be considerate of the OpenMeteo API.
# Do not overload it. Please? Thanks!
curl -s "https://archive-api.open-meteo.com/v1/archive?"\
"latitude=45.9764&longitude=7.6586&"\
"elevation=4478&timezone=Europe/Zurich&"\
"start_date=1976-01-01&end_date=2025-12-31&"\
"hourly=temperature_2m,precipitation,cloud_cover,cloud_cover_low,snowfall,snow_depth"\
> matterhorn-1976-2025.json"

The only missing ingredient was pandas, an excellent Python library for data manipulation and analysis: think Excel + major steroids (minus Copilot and proprietary bullshit).

Matterhorn Pandas
Matterhorn + panda (credits Caramelized Onions and Sheilalau)

I whipped up a simple python analysis script summi using pandas and matplotlib and dropped it, of course, on CodeBerg.

Usage instructions (click)
$ ./summi --help
usage: summi [--help] [-b ROLLING_BEST | -m ROLLING_MEAN] [-p MIN_PRECIPITATION] [-h MIN_HOUR] [-H MAX_HOUR] [-y MIN_YEAR] [-Y MAX_YEAR] [-d MIN_MONTH_DAY]
             [-D MAX_MONTH_DAY] [-o [HOURLY ...]] [-l LEGEND_LOC] [-t TITLE] [-u SUBTITLE]
             {c,cloud,p,prec,precipitation,s,snow,t,temp,temperature}

Display location-specific weather conditions and charts. Reads input as a JSON file downloaded from Open-meteo.
 * URL path: "https://archive-api.open-meteo.com/v1/archive"
 * URL parameters:
    - latitude, longitude, elevation
    - start_date, end_date (YYYY-MM-DD)
    - timezone (timezone name from tz database)
    - hourly=temperature_2m,precipitation,cloud_cover,cloud_cover_low,snowfall,snow_depth
 * Docs: https://open-meteo.com/en/docs/historical-forecast-api

positional arguments:
  {c,cloud,p,prec,precipitation,s,snow,t,temp,temperature}
                        Graph to diplay.

options:
  --help                show this help message and exit
  -b ROLLING_BEST, --rolling-best ROLLING_BEST
                        Calculate rolling "optimistic" (min/max) aggregates over a number of days. Must be between 2 and 30.
  -m ROLLING_MEAN, --rolling-mean ROLLING_MEAN
                        Calculate rolling (mean) aggregates over a number of days. Must be between 2 and 30.
                        Useful for smoothing jagged graphs.
  -p MIN_PRECIPITATION, --min-precipitation MIN_PRECIPITATION
                        Minimum amount of precipitation (mm) and snowfall (cm) for which it is considered "rainy" or "snowing"
  -h MIN_HOUR, --min-hour MIN_HOUR
                        Minimum hour (24h clock; inclusive). Must be below --max-hour (default 0)
  -H MAX_HOUR, --max-hour MAX_HOUR
                        Maximum hour (24h clock; inclusive). Must be below 24 (default 24)
  -y MIN_YEAR, --min-year MIN_YEAR
                        Minimum year (inclusive; default None)
  -Y MAX_YEAR, --max-year MAX_YEAR
                        Maximum year (inclusive; default None).
  -d MIN_MONTH_DAY, --min-month-day MIN_MONTH_DAY
                        Minimum month/day (MM/DD); inclusive; default None).
  -D MAX_MONTH_DAY, --max-month-day MAX_MONTH_DAY
                        Maximum month/day (MM/DD); inclusive; default None).
  -o [HOURLY ...], --hourly [HOURLY ...]
                        Generate hourly aggregate graphs, one for each day (MM/DD) included as parameter or for the whole period.
  -l LEGEND_LOC, --legend-loc LEGEND_LOC
                        Position ("loc") of the legend on the graph. See https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html
  -t TITLE, --title TITLE
                        Title of the graph. Your move, human!
  -u SUBTITLE, --subtitle SUBTITLE
                        Subtitle of the graph. Go wild!

Copyright (c) 2026 Manuel Zahariev.  License GPLv3: GNU GPL version 3 <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.  There is NO WARRANTY, to the extent permitted by law.

Snow #

I plot snowfall and snow depth (difference from the annual minimum). To smoothen jagged edges, I use a 7-day rolling average for the snowfall, reporting the value at the start of the window.

Matterhorn snow conditions
Command (click)
cat matterhorn-1976-2025.json | ./summi snow \
 --rolling-mean 7 \
 --title "Matterhorn snow conditions" \
 --subtitle "7-day rolling average. 1976-2025."

Conclusion: snow conditions dictate the summer climbing window:

Temperature #

I look at temperature during a 8-10AM summit window and average the highest temperatures (minimum and maximum) within 3 days.

The bands? Standard deviation.

Matterhorn Summit temperature Aug-Sep
Command (click)
cat matterhorn-1976-2025.json | ./summi temperature \
 --min-month-day 07/01 --max-month-day 09/15 \
 --min-hour 9 --max-hour 12 \
 --title "Temperature (Matterhorn)" \
 --subtitle "3-day rolling maximum. 1976-2025. 9AM-12PM (Europe/Zurich)"

Conclusion: the summit is cold!

I'll make sure to bring a jacket.

Precipitation #

Precipitation is trickier to report:

Matterhorn Summit precipitation Aug-Sep
Command (click)
cat matterhorn-1976-2025.json | ./summi precipitation \
 --min-precipitation 0 \
 --min-month-day 07/01 --max-month-day 09/15 \
 --min-hour 4 --max-hour 12 \
 --rolling-best 3 \
 --title "Precipitation (Matterhorn)" \
 --subtitle "3-day rolling minimum. 1976-2025. 4AM-12PM (Europe/Zurich)."

Conclusions:


Intermission: The minimum (probability zero) of morning rain on every day between September 4-6 should be taken with a grain of salt. I only have 50 years of data and the climate is changing. Without going into the rabbit hole of probability density, kurtosis and probability distribution of daily precipitation you should (pun 🤪) probably not treat it as zero: it may rain for three straight days in 2026. Or 2027.


I ran about 50 plots or so before getting to this point, then I booked the hut and flights for a September 5-7 summit window, with a target September 6 summit day. The probability of at least one dry morning in these three days is 96%. Not bad.

The Sep 4-6 window may have looked better (100% probability), but flights were a lot more complicated3.

5. What to expect? #

I plot average precipitation for each hour on a few dates in July, August and September over all 50 years in the dataset.

Matterhorn Summit hourly precipitation for a few given dates.
Command (click)
cat matterhorn-1976-2025.json | ./summi precipitation \
 --hourly 07/06 08/06 08/21 09/06 \
 --title "Hourly precipitation (Matterhorn)" \
 --subtitle "1976-2025."

Conclusions:


I also plot average temperatures for each hour on the same dates.

Matterhorn Summit hourly temperature for a few given dates.
Command (click)
cat matterhorn-1976-2025.json | ./summi temperature \
 --hourly 07/06 08/06 08/21 09/06 \
 --title "Hourly temperature (Matterhorn)" \
 --subtitle "1976-2025."

Conclusions:

6. Trip #

So after all this, here is my trip plan:

If the weather does not cooperate on September 6 (22% chance of rain), summit on September 7 or 5. Bail if the weather is bad on all three mornings (4% chance).

I'll let you know how it goes!


  1. The Hörnli Hut is open between the drop in daily snowfall (late June) and the start of new snow accummulation (mid-September). Very cool! ↩︎

  2. Snowfall is included in the total for precipitation. "For the water equivalent in millimeter, divide by 7. E.g. 7 cm snow = 10 mm" (Historical Weather API). ↩︎

  3. Optimizing air travel using pandas in the age of dynamic pricing seems like another worthwile, if formidable endeavor. ↩︎

last updated: