Pages (Desktop)

Pages (Mobile)

Walter and Lieth climate diagrams in R

Climate diagrams are useful tools which provide a visual summary of average climate conditions for a place over a specified period of time. This guide will explain the different parts of a Walter and Lieth climate diagram, and show you how to create one in R using the "climatol" package. This package provides a really quick and easy way to make good-looking Walter and Lieth climate diagrams. But, this guide will also show you how to create one from scratch (no packages needed!).

Guide Information

Title Walter and Lieth climate diagrams in R
Author Benjamin Bell
Published April 19, 2018
Last updated August 12, 2021
R version 3.5.0
Packages base; climatol

This guide has been updated:

  • The previous version of this guide used the "iki.dataclim" package to quickly make a Walter and Lieth diagram. However, this package is no longer available on CRAN. The guide now uses the "climatol" package.

Understanding Walter and Lieth climate diagrams

Walter and Lieth (1967) climate diagrams are great for showing a summary of climate conditions for a place over a specific time period. They are especially useful for categorising climate conditions to group locations with similar climate, and for showing moisture conditions (wet, dry, humid periods).

Walter and Lieth climate diagrams are made up of several parts:

https://www.benjaminbell.co.uk about="https://www.benjaminbell.co.uk" dc:publisher="https://www.benjaminbell.co.uk"> 0 10 20 30 40 50 0 20 40 60 80 100 300 C mm Vancouv er [Lat: 49.3, Lon: -123.1] (82 m) 1970 to 2000 A v er age T emp . 9.5C Ann ual Precip . 1590 mm Max 21.6 Min 0.4 J F M A M J J A S O N D 0 10 20 30 40 50 0 20 40 60 80 100 300 C mm Marr ak ech [Lat: 31.6, Lon: -8.0] (466 m) 1970 to 2000 A v er age T emp . 19.4C Ann ual Precip . 302 mm Max 36.5 Min 5.5 J F M A M J J A S O N D 1 3 4 2 5 6 Wet period Dry period Humid period https://www.benjaminbell.co.uk

1. Location or station name, along with coordinates, altitude, and the period of observation.

2. Average annual conditions - mean temperature, and mean annual precipitation (MAP).

3. Mean daily monthly precipitation.

4. Mean daily monthly temperature.

5. Maximum temperature (of the warmest month), and minimum temperature (of the coldest month).

6. Indication of months where frost is likely.

The diagrams show both mean daily temperature and precipitation for each month. The left y axis shows temperature (℃) from 0 to 50℃, while the right y axis shows precipitation (mm) from 0 to 100 mm. Precipitation above 100 mm/month is also shown on the right y axis, but at a reduced scale.

Months are shown along the x axis, and where frost is likely, this is indicated by the coloured box. Sometimes this is colour-coded for "likely" frost and "definite" frost.

The temperature curve is shown in red, and the precipitation curve is shown in blue. Where the precipitation curve is above the temperature curve, this period will be relatively humid. Where the precipitation curve falls below the temperature curve, this period will be relatively dry. Where the precipitation curve goes above 100 mm, this period will be relatively wet.

© Benjamin Bell. All Rights Reserved. https://www.benjaminbell.co.uk

Getting the climate data

To create Walter and Lieth climate diagrams, you'll need daily precipitation, and daily minimum and maximum temperature data for your location. If you do not have daily data, monthly averages are also fine (this is what we'll use in this guide).

You can get the climate data from CRU - to find out how to do this, please check out my earlier guide for getting climate data.

For this guide, we are going to extract climate data for three locations: Manchester, Marrakech and Vancouver. We will then calculate the average monthly climate conditions for the period 1970 to 2000 for our three climate variables: precipitation, minimum and maximum temperatures. Finally, we will create three matrices for each location containing the climate data, and export these to csv files (optional).

To understand how this code works, please check out the working with CRU climate data guide, which explains each part of the code.

## Get Climate Data for Walter and Lieth climate diagrams
# Full guide available at: https://www.benjaminbell.co.uk

# Load packages
library(raster)
library(ncdf4)

### Change location of files for your system ###
# Load the CRU TS datasets into R as a "RasterBrick" object
pre <- brick("cru_ts4.01.1901.2016.pre.dat.nc", varname="pre") # Precipitation
tmin <- brick("cru_ts4.01.1901.2016.tmn.dat.nc", varname="tmn") # Min monthly temperature
tmax <- brick("cru_ts4.01.1901.2016.tmx.dat.nc", varname="tmx") # Max monthly temperature

# Create "samples" matrix
site <- c("Manchester", "Marrakech", "Vancouver")
lon <- c(-2.24, -8, -123.12)
lat <- c(53.47, 31.63, 49.25)
samples <- matrix(c(lon, lat), ncol=2)
rownames(samples) <- site
colnames(samples) <- c("lon", "lat")

## Extract climate data from the CRU datasets "RasterBrick"
pre.sites <- as.data.frame(extract(pre, samples, ncol=2)) # Precipitation
tmin.sites <- as.data.frame(extract(tmin, samples, ncol=2)) # Min monthly temperature
tmax.sites <- as.data.frame(extract(tmax, samples, ncol=2)) # Max monthly temperature
# Add sample site names to the data.frame
row.names(pre.sites) <- row.names(samples)
row.names(tmin.sites) <- row.names(samples)
row.names(tmax.sites) <- row.names(samples)

# Change column names
years <- 1901:2016
month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
names(pre.sites) <- paste(rep(years, each=12), rep(month, times=116), sep="_")
names(tmin.sites) <- paste(rep(years, each=12), rep(month, times=116), sep="_")
names(tmax.sites) <- paste(rep(years, each=12), rep(month, times=116), sep="_")

# Calculate monthly data for the period 1970 - 2000
pre1970 <- pre.sites[829:1188]
tmin1970 <- tmin.sites[829:1188]
tmax1970 <- tmax.sites[829:1188]

# Precip - mean monthly total
pre1970.mean <- as.data.frame(sapply(month, function(x) rowMeans(pre1970[, grep(x, names(pre1970))])))
names(pre1970.mean) <- month # Rename columns in the new data frame object

# Temp - mean monthly min (in place of daily min)
tmin1970.mean <- as.data.frame(sapply(month, function(x) rowMeans(tmin1970[, grep(x, names(tmin1970))])))
names(tmin1970.mean) <- month # Rename columns

# Temp - absolute monthly min (in place of daily min)
tmin1970.min <- as.data.frame(sapply(month, function(x) apply(tmin1970[, grep(x, names(tmin1970))], 1, FUN=min)))

# Temp - mean monthly max (in place of daily max)
tmax1970.mean <- as.data.frame(sapply(month, function(x) rowMeans(tmax1970[, grep(x, names(tmax1970))])))
names(tmax1970.mean) <- month # Rename columns

# Create matrix of climate data needed for Walter and Lieth diagram
# Manchester
man <- as.matrix(rbind(pre1970.mean[1,], tmax1970.mean[1,], tmin1970.mean[1,], tmin1970.min[1,])) 
rownames(man) <- c("Precip", "MaxT", "MinT", "AbsMinT")
# Marrakech
mar <- as.matrix(rbind(pre1970.mean[2,], tmax1970.mean[2,], tmin1970.mean[2,], tmin1970.min[2,]))  
rownames(mar) <- c("Precip", "MaxT", "MinT", "AbsMinT")
# Vancouver
van <- as.matrix(rbind(pre1970.mean[3,], tmax1970.mean[3,], tmin1970.mean[3,], tmin1970.min[3,]))
rownames(van) <- c("Precip", "MaxT", "MinT", "AbsMinT")

### This step is optional ###
# Export the extracted climate data to a csv files
write.csv(man, file="Manchester 1970-2000 Climate.csv")
write.csv(mar, file="Marrakech 1970-2000 Climate.csv")
write.csv(van, file="Vancouver 1970-2000 Climate.csv")

This code extracts climate data from CRU TS datasets for our three locations (using the samples matrix) and calculates monthly average data for the period 1970 to 2000.

The data is converted to a matrix for each location, containing precipitation, maximum temperatures, minimum temperatures, and absolute minimum temperatures (the lowest temperature for that month). This is the data that is used to create a Walter and Lieth climate diagram.

Please check out the working with CRU climate data guide, for a more detailed explanation of this code.

An optional step is to export the climate data as a csv file. If you need to come back to the project later, this saves you from having to re-run the above code - you can simply import the data you have already extracted and calculated back into R.

I've uploaded the climate data for the three sites to Google Sheets - you can download these files to follow this guide (without having to extract the data yourself).

Manchester climate data 1970-2000

Marrakech climate data 1970-2000

Vancouver climate data 1970-2000

To import these files into R, use the following code:

# Import climate data
man <- as.matrix(read.csv("Manchester 1970-2000 Climate.csv", row.names=1))
mar <- as.matrix(read.csv("Marrakech 1970-2000 Climate.csv", row.names=1))
van <- as.matrix(read.csv("Vancouver 1970-2000 Climate.csv", row.names=1))

(You only need to run this code if you have previously exported the climate data and exited R, before creating the climate diagram).

© Benjamin Bell. All Rights Reserved. https://www.benjaminbell.co.uk

Walter and Lieth diagrams using "climatol" package

By far, the easiest and quickest way to make a Walter and Lieth climate diagram in R, is to use the diagwl function from the "climatol" package.

To install the package, type install.packages("climatol") in the R console, and to load the package, type library(climatol) when you first start R.

For the function to work, the climate data needs to be contained within a matrix. This should have 12 columns (one for each month) and four rows in this order: precipitation, maximum temperature, minimum temperature and absolute minimum temperature (lowest monthly temps).

Using the climate data we extracted in the previous section, the following code will create Walter and Lieth climate diagrams:

# Load package
library(climatol)

# Plot Walter and Lieth climate diagrams
# Manchester
diagwl(man, est="Manchester [Lat: 53.5, Lon: -2.2]", alt="38", per="1970 to 2000")
# Marrakech
diagwl(mar, est="Marrakech [Lat: 31.6, Lon: -8.0]", alt="466", per="1970 to 2000")
# Vancouver
diagwl(van, est="Vancouver [Lat: 49.3, Lon: -123.1]", alt="82", per="1970 to 2000")

The resulting output for Manchester is shown below (Marrakech and Vancouver climate diagrams were shown at the start of the guide).

https://www.benjaminbell.co.uk 0 10 20 30 40 50 0 20 40 60 80 100 300 C mm Manchester [Lat: 53.5, Lon: -2.2] (38 m) 1970 to 2000 Average Temp. 9.3C Annual Precip. 862 mm Max 20.1 Min 1.0 J F M A M J J A S O N D

Arguments to use with the diagwl function.

est
This argument is a character string which contains the name of the climate station (or the location) for the diagram. Usually, the latitude and longitude coordinates are included in Walter and Lieth climate diagrams - so you can include them using this argument.
alt
This argument is a character string which contains the altitude (elevation) of the climate station (or location).
per
This argument is a character string which contains the period of time which the climate diagram represents.
pcol
This argument allows you to specify the colour for precipitation. (Ideally, this should be a shade of blue).
tcol
This argument allows you to specify the colour for temperature. (Ideally, this should be a shade of red).
pfcol
This argument allows you to specify the colour to represent "probable frost" (frost is likely to occur for that month). This appears as coloured boxes along the x axis.
sfcol
This argument allows you to specify the colour to represent "sure frost" (frost is almost certain for that month). This appears as coloured boxes along the x axis.
shem
This is a logical argument to specify whether the climate station (or location) is in the southern hemisphere. The default value is FALSE. If the value is TRUE, the x axis will change to July to June (rather than January to December).
p3line
This is a logical argument which will draw an additional precipitation curve at "three times the temperature curve" (the extra curve will appear between the actual precipitation curve, and the temperature curve). The default value is FALSE.

You can use any source of climate data and any period to create Walter and Lieth climate diagrams.

© Benjamin Bell. All Rights Reserved. https://www.benjaminbell.co.uk

Creating Walter and Lieth diagrams "from scratch"

As the previous section shows, it is really simple to create Walter and Lieth climate diagrams using the climatol package. But, you can also create a similar Walter and Lieth diagram in R "from scratch" without using any packages. This is much more involved, and not as "automated" as using the previous examples. There's really no reason not to use the climatol package if you are happy with the plot output, but, it is fun to mess around in R!

To start, we'll re-create the Manchester climate diagram (since this is the most straightforward), reusing the data created in the previous sections.

The first step is to calculate the mean temperature data from the minimum and maximum temperature rows in the man matrix:

# Calculate mean temp data
temp <- colMeans(man[2:3,])

Next, we need to manipulate the precipitation data. On Walter and Lieth diagrams, the temperature scale is from 0 to 50, while the precipitation scale is from 0 to 100, and then 100 to 300. As the Manchester monthly precipitation values are all below 100, all we need to do to ensure that the precipitation curve properly scales with the temperature curve, is divide the values by 2.

# Get precip values from matrix
precip <- as.numeric(man[1,])

# Divide values by 2 to match temperature scale
precip <- precip/2

Now, we can start to plot the data! We'll start by creating the x axis to represent the months, plot the temperature curve, and add the precipitation curve.

# Months axis
month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
m <- 1:12

# Plot Temperature
par(mar=c(5,5,3,5))
plot(m, temp, type="l", lwd=2.4, ylim=c(0, 60), xaxs="i", yaxs="i", ann=FALSE, axes=FALSE, col="#FA4141")
# Add precipitation
lines(precip, lwd=2.4, col="#0E67F5")

It is important to set the ylim argument as ylim=c(0, 60) to ensure the temperature and precipitation curves scale correctly. This is the first "cheat" we'll use to plot our diagram. We'll add the axis labels later.

The arguments xaxs="i" and yaxs="i" remove whitespace on the plot region.

Next, we'll add the "humid" shading to the plot (these are the blue vertical lines):

# Humid vertical lines shading
polygon(x=c(m, rev(m)), y=c(precip, rev(temp+0.2)), density=10, angle=90, col="#0E67F5", border=NA) 

polygon() is used to create our shaded area between the temperature and precipitation curve. This requires x and y coordinates of where to draw the polygon shape - the coordinates go from top-left to top-right, to bottom-right, to bottom-left.

The x coordinates are simply the values 1 to 12, plus, 1 to 12 in reverse. These values are contained in the m object. To reverse the values, we use the rev() function, and use the combine function c() to add them together, resulting in the x argument: x=c(m, rev(m)).

The y coordinates are the values of the precipitation curve, plus, the values of the temperature curve in reverse. To add the shaded lines just above the temperature curve, we add +0.2 to the values. The resulting y argument is: y=c(precip, rev(temp+0.2)).

This will result in the following plot:

Next, we'll add the horizontal line at 50℃ and 100 mm, and add the plot axes.

# Add line at 50C / 100mm
abline(h=50)

# Axes
axis(1, las=1, tck=-0.02, at=m, labels=month)
# Temp
axis(2, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 10, 20, 30, 40, 50, NA), col.axis="#FA4141")
# Precip
axis(4, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 20, 40, 60, 80, 100, 300), col.axis="#0E67F5")

This is our next "cheat" - For the temperature axis (2), we position the labels every 10℃, and label them the same, but we do not want a label for "60℃", so we use NA. For the precipitation axis (4), the labels will be in the same "position" as the temperature axis, but their label value will reflect the precipitation scale: labels=c(0, 20, 40, 60, 80, 100, 300).

Lastly, we'll add all the labels to the plot:

# Labels - Manchester
# Station/Location
mtext("Manchester", side=3, at=1, line=3.5, adj=0, cex=1.2, font=2)
# Coordinates
mtext("Lat: 53.5, Lon: -2.2, Alt: 38m", side=3, at=1, line=2, adj=0, cex=1.2)
# Period
mtext("1970 to 2000", side=3, at=1, line=0.5, adj=0, cex=1.2)
# Average temp
mtext(paste("Mean temp: ", round(mean(temp), 1), "\U00B0", "C", sep=""), side=3, at=12, line=2, adj=1, cex=1.2)
# Mean annual precip
mtext(paste("Annual precip: ", round(sum(man[1,]), 0), " mm", sep=""), side=3, at=12, line=0.5, adj=1, cex=1.2)
# Temperature
mtext("\n(\U00B0 C)", side=2, at=56, line=1.5, las=1, col="#FA4141")
# Max temp
mtext(paste("Max\n", round(max(man[2,]), 1),  sep=""), side=2, at=45, line=1.5, las=1)
# Min temp
mtext(paste("Min\n", round(min(man[3,]), 1),  sep=""), side=2, at=5, line=1.5, las=1)
# Precip
mtext("(mm)", side=4, at=56, line=1.5, las=1, col="#0E67F5")

This code is fairly self-explanatory, mtext() is used to position text around the plot. Temperature and precipitation values are calculated from the man matrix.

So, the final plot will look like this:

Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 0 10 20 30 40 50 0 20 40 60 80 100 300 Manchester Lat: 53.5, Lon: -2.2, Alt: 38m 1970 to 2000 Mean temp: 9.3°C Annual precip: 862 mm (°C) Max 20.1 Min 1 (mm)

The final figure looks pretty good - and was simple enough to produce.

Next, we'll re-create the Vancouver climate diagram. We'll calculate mean temperature in the same way as for Manchester. But, Vancouver has monthly precipitation values above 100 mm. To ensure that the precipitation curve properly scales with the temperature curve, and to account for the change from in the precipitation scale (the jump from 100 to 300), we'll do two things to the data.

First, we need to scale the precipitation values above 100 mm to match the scale on the plot. Up until 100 mm, the plot "increments" represent 20 mm, but after 100 mm, they represent 200 mm. So, we need to make the precipitation values above 100 mm 10 times smaller, and then add 90 so they remain above 100 mm.

# Calculate mean temp data
temp <- colMeans(van[2:3,])

# Get precip values from matrix
precip <- as.numeric(van[1,])

# Scale values above 100 mm
precip[precip>100] <- precip[precip>100] * 0.1 + 90

Then we'll divide the precipitation values by 2, so it scales with the temperature plot scale.

# Divide values by 2 to match temperature scale
precip <- precip/2

We'll plot the data and add the "humid" shading, as we did for the Manchester example:

# Months axis
month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
m <- 1:12

# Plot Temperature
par(mar=c(5,5,5,5))
plot(m, temp, type="l", lwd=2.4, ylim=c(0, 60), xaxs="i", yaxs="i", ann=FALSE, axes=FALSE, col="#FA4141")
# Add precipitation
lines(precip, lwd=2.4, col="#0E67F5")

# Humid vertical lines shading
polygon(c(m,rev(m)), c(precip, rev(temp+0.2)), density=10, angle=90, col="#0E67F5", border=NA) 

Next, we need to add solid shading to represent the "wet" period (months with > 100 mm precipitation).

This can be done in several ways - for example, by finding the point where the precipitation curve intercepts the 100 mm line. But, since we're just making one graph, we'll "cheat" and do this in a simple way.

First, we'll use the ifelse() function to alter the y coordinates of our polygon:

wet <- ifelse(precip > 50, precip, 50))

Essentially, we want values below 50 to become 50 (this will make sense in a moment!). Then, we'll add the shading using these new values:

polygon(x=c(m, rev(m)), y=c(wet, rep(50, times=12)), col="#0E67F5", border=NA) 

This works fairly well, except the shape of the solid shading extends outside the precipitation curve:

An easy fix, is to plot a new white polygon above the precipitation curve to cover the overlaps. This is not the best solution, but it is simple!

# "remove" solid colour below 50
polygon(x=c(m, rev(m)), y=c(precip+0.2, rep(60, times=12)), col="white", border=NA) 

Finally, we'll add the axes and labels:

# Add line at 50C / 100mm
abline(h=50)

# Axes
axis(1, las=1, tck=-0.02, at=m, labels=month)
# Temp
axis(2, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 10, 20, 30, 40, 50, NA), col.axis="#FA4141")
# Precip
axis(4, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 20, 40, 60, 80, 100, 300), col.axis="#0E67F5")

# Labels - Vancouver
# Station/Location
mtext("Vancouver", side=3, at=1, line=3.5, adj=0, cex=1.2, font=2)
# Coordinates
mtext("Lat: 49.3, Lon: -123.1, Alt: 82m", side=3, at=1, line=2, adj=0, cex=1.2)
# Period
mtext("1970 to 2000", side=3, at=1, line=0.5, adj=0, cex=1.2)
# Average temp
mtext(paste("Mean temp: ", round(mean(temp), 1), "\U00B0", "C", sep=""), side=3, at=12, line=2, adj=1, cex=1.2)
# Mean annual precip
mtext(paste("Annual precip: ", round(sum(van[1,]), 0), " mm", sep=""), side=3, at=12, line=0.5, adj=1, cex=1.2)
# Temperature
mtext("\n(\U00B0 C)", side=2, at=56, line=1.5, las=1, col="#FA4141")
# Max temp
mtext(paste("Max\n", round(max(van[2,]), 1),  sep=""), side=2, at=45, line=1.5, las=1)
# Min temp
mtext(paste("Min\n", round(min(van[3,]), 1),  sep=""), side=2, at=5, line=1.5, las=1)
# Precip
mtext("(mm)", side=4, at=56, line=1.5, las=1, col="#0E67F5")

The final figure should look like this:

Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 0 10 20 30 40 50 0 20 40 60 80 100 300 Vancouver Lat: 49.3, Lon: -123.1, Alt: 82m 1970 to 2000 Mean temp: 9.5°C Annual precip: 1590 mm (°C) Max 21.6 Min 0.4 (mm)

Lastly, we'll re-create the Marrakech climate diagram. Like Manchester, Marrakech has no monthly precipitation values above 100 mm, so we'll calculate the mean temperature values, and divide the precipitation values by 2. We'll then start to plot the data - this time, we'll create an empty plot, adding the temperature curve and precipitation curves later:

# Calculate mean temp data
temp <- colMeans(mar[2:3,])

# Get precip values from matrix
precip <- as.numeric(mar[1,])

# Divide precipitation values by 2 to match temperature scale
precip <- precip/2

# Months axis
month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
m <- 1:12

# Empty Temperature plot
par(mar=c(5,5,5,5))
plot(m, temp, type="n", lwd=2.4, ylim=c(0, 60), xaxs="i", yaxs="i", ann=FALSE, axes=FALSE, col="#FA4141")

# Humid vertical lines shading
polygon(x=c(m, rev(m)), y=c(precip, rev(temp+0.2)), density=10, angle=90, col="#0E67F5", border=NA) 

Which will result in the following plot:

Currently, the middle is shaded with vertical lines - but this area is a "dry" period, and should instead be shaded with red dots. So, we'll use a similar "cheat" to the one we used previously to cover these lines. We'll plot a white polygon above the precipitation line, and below the temperature line in the middle, and then add the red dots. Again, this is not the best solution, but it is really simple!

First, we'll use the ifelse() function to alter the y coordinates:

dry <- ifelse(precip < temp, temp, precip)

And then add the shading:

# Remove vertical lines
polygon(x=c(m, rev(m)), y=c(dry + 0.4, rev(precip - 0.4)), col="white",  border=NA)
# Add red dots
polygon(x=c(m, rev(m)), y=c(dry - 0.15, rev(precip + 0.15)), density=10, lty=c("16"), lwd=1, col="#FA4141", border=NA)

Now, we'll add the temperature and precipitation curves:

lines(temp, lwd=2.4, col="#FA4141")
lines(precip, lwd=2.4, col="#0E67F5")

Which should result in the following plot:

Finally, we'll add the axes and labels:

# Add line at 50C / 100mm
abline(h=50)

# Axes
axis(1, las=1, tck=-0.02, at=m, labels=month)
# Temp
axis(2, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 10, 20, 30, 40, 50, NA), col.axis="#FA4141")
# Precip
axis(4, las=2, tck=-0.02, at=c(0, 10, 20, 30, 40, 50, 60), labels=c(0, 20, 40, 60, 80, 100, 300), col.axis="#0E67F5")

# Labels - Marrakech
# Station/Location
mtext("Marrakech", side=3, at=1, line=3.5, adj=0, cex=1.2, font=2)
# Coordinates
mtext("Lat: 53.5, Lon: -2.2, Alt: 466m", side=3, at=1, line=2, adj=0, cex=1.2)
# Period
mtext("1970 to 2000", side=3, at=1, line=0.5, adj=0, cex=1.2)
# Average temp
mtext(paste("Mean temp: ", round(mean(temp), 1), "\U00B0", "C", sep=""), side=3, at=12, line=2, adj=1, cex=1.2)
# Mean annual precip
mtext(paste("Annual precip: ", round(sum(mar[1,]), 0), " mm", sep=""), side=3, at=12, line=0.5, adj=1, cex=1.2)
# Temperature
mtext("\n(\U00B0 C)", side=2, at=56, line=1.5, las=1, col="#FA4141")
# Max temp
mtext(paste("Max\n", round(max(mar[2,]), 1),  sep=""), side=2, at=45, line=1.5, las=1)
# Min temp
mtext(paste("Min\n", round(min(mar[3,]), 1),  sep=""), side=2, at=5, line=1.5, las=1)
# Precip
mtext("(mm)", side=4, at=56, line=1.5, las=1, col="#0E67F5")

The final figure should look like this:

Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 0 10 20 30 40 50 0 20 40 60 80 100 300 Marrakech Lat: 53.5, Lon: -2.2, Alt: 466m 1970 to 2000 Mean temp: 19.4°C Annual precip: 302 mm (°C) Max 36.5 Min 5.5 (mm)

The final Walter and Lieth climate diagrams are pretty close to what is produced by the climatol package. There were a few "cheats" used, and better solutions exist - but these examples are a quick and simple way to create climate diagrams without using a package. Unless you need to customise the plots further (e.g. changing density of shading lines/dots), it is probably best to stick with using climatol.

However, one such customisation you might want to try, is to plot the temperature and precipitation curves as "stairs". To do this, alter the plot code to type="s", and change the shading from polygon() to segments(). Heres an example for Manchester:

# Create empty plot
par(mar=c(5,5,5,5))
plot(m, temp, type="n", lwd=2.4, ylim=c(0, 60), xaxs="i", yaxs="i", ann=FALSE, axes=FALSE, col="#FA4141")

# Humid vertical lines
m2 <- c(m, m+0.25, m+0.5, m+0.75)
segments(x0=m2, x1=m2, y0=precip, y1=temp, col="#0E67F5")

# Add temp and precipitation "stairs"
lines(temp, type="s", lwd=2.4, col="#FA4141")
lines(precip, type="s", lwd=2.4, col="#0E67F5")

After adding the axes and labels, the final plot would look like this:

Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 0 10 20 30 40 50 0 20 40 60 80 100 300 Manchester Lat: 53.5, Lon: -2.2, Alt: 38m 1970 to 2000 Mean temp: 9.3°C Annual precip: 862 mm (°C) Max 20.1 Min 1 (mm)

Thanks for reading! Please leave any comments or questions below.

© Benjamin Bell. All Rights Reserved. http://www.benjaminbell.co.uk

Further reading

Sources of climate data - This quick guide shows you where to find climate datasets, and raw climate station data.

Getting Climate Data - This guide will take you through the steps to download and extract climate data from CRU for your project.

Working with extracted CRU climate data - This guide will show you how to work with your downloaded CRU climate data, perform analysis and make climate plots.

9 comments

  1. Hello, What if I do not have a weather station but download data from on online source and did a bias correction? I did that and now want to plot my bias corrected data

    ReplyDelete
    Replies
    1. Sure - as long as you have monthly data that should be fine. You can mention the data source next to the place name.

      Delete
  2. Hi Ben,
    Thank you for this very useful post. I am trying to combine two Walter and Lieth climate diagrams into one overall graph in R using the iki.dataclim. I am using par(mfrow=c(1,2)) but it doesn't work and I get two separate plots with the figure left aligned. Any ideas would be helpful. Thank you! - Shasank Ongole.

    ReplyDelete
    Replies
    1. Hi Shasank,

      The problem occurs because the plot function in iki.dataclim package overrides the graphical device parameters with its own. So, however you tell R to lay out the screen, iki.dataclim will override it.


      There is a good blog post which explains the problem and provides some solutions - Take a look here: https://www.andrewheiss.com/blog/2016/12/08/save-base-graphics-as-pseudo-objects-in-r/


      However, I've found this still does not work when trying to use two iki.dataclim plots side by side. But, it would let you plot a iki.dataclim plot and another base graphics plot side by side.

      I am not aware of another solution to get this to work in R.

      One workaround would be to create two separate plots, save as images and stick them together in another program. Or, you can create the Walter and Lieth diagram manually (as in this guide) and then use par(mfrow=c(1,2)).

      Delete
  3. Hi Ben,
    Thank you for your response! Will check out the link and workarounds.

    ReplyDelete
  4. Man, that really helped me a lot! I really like the base R approach. Thanks a lot and keep up the good work :) Paul

    ReplyDelete
  5. Man, that really helped me a lot! I really like the base R approach. Thanks a lot and keep up the good work. Paul

    ReplyDelete
  6. Hey, I am plotting a Walter Lieth diagramm "from scratch" with both, rain above 100 mm per month and a dry phase. I am not able to add the red dotted area between the two lines when i use your second example as "basis" to draw my plot. Is it possible to combine both, dark blue >100 mm and red dotted area when precipitation < temperature? Thanks for your help! :)

    ReplyDelete
    Replies
    1. Hi Jakob,

      Does the problem occur if you use the climatol package to produce the diagram? I suspect there is an error in my code. Would it be possible to email me with the code and data you are using so i can try and figure out the issue?

      Best wishes,
      Ben

      Delete

Comments are moderated. There may be a delay until your comment appears.