5  Wind and Pollution Roses

Author

David Carslaw

The wind rose is a very useful way of summarising meteorological data. It is particularly useful for showing how wind speed and wind direction conditions vary by year. The windRose function can plot wind roses in a variety of ways: summarising all available wind speed and wind direction data, plotting individual wind roses by year, and also by month. The latter is useful for considering how meteorological conditions vary by season.

Data are summarised by direction, typically by 45 or 30\(^\circ\) and by different wind speed categories. Typically, wind speeds are represented by different width ‘paddles’. The plots show the proportion (here represented as a percentage) of time that the wind is from a certain angle and wind speed range.

The windRose function also calculates the percentage of ‘calms’ i.e. when the wind speed is zero. UK Met Office data assigns these periods to 0 degrees wind direction with valid northerly winds being assigned to 360\(^\circ\). The option calm.thresh can be used to assign calms to non-zero wind speeds. For example calm.thresh = 0.5 will assign wind speeds below 0.5 as calm.

The windRose function will also correct for bias when wind directions are rounded to the nearest 10 degrees but are displayed at angles that 10 degrees is not exactly divisible into e.g. 22.5\(^\circ\). When such data are binned, some angles i.e. N, E, S, W will comprise three intervals whereas others will comprise two, which can lead to significant bias. This issue and its solution is discussed by Droppo and Napier (2008) and Applequist (2012).1 openair uses a simple method to correct for the bias by globally rescaling the count in each wind direction bin by the number of directions it represents relative to the average. Thus, the primary four directions are each reduced by a factor of 0.75 and the remaining 12 directions are multiplied by 1.125.

Droppo, James G, and Bruce A Napier. 2008. “Wind Direction Bias in Generating Wind Roses and Conducting Sector-Based Air Dispersion Modeling.” Journal of the Air & Waste Management Association 58 (7): 913–18.

5.1 Example of use

First we load the packages:

The function is very simply called as shown for Figure 5.1.

windRose(mydata)
Figure 5.1: Use of windRose function to plot wind speed/direction frequencies. Wind speeds are split into the intervals shown by the scale in each panel. The grey circles show the % frequencies.

Figure 5.2 highlights some interesting differences between the years. In 2000, for example, there were numerous occasions when the wind was from the SSW and 2003 clearly had more occasions when the wind was easterly. It can also be useful to use type = "month" to get an idea of how wind speed and direction vary seasonally.

windRose(
  mydata,
  type = "year",
  layout = c(4, 2),
  width = 0.5
)
Figure 5.2: Use of windRose function to plot wind speed/direction frequencies by year. Wind speeds are split into the intervals shown by the scale in each panel. The grey circles show the 10 and 20% frequencies.

The type option is very flexible in openair and can be used to quickly consider the dependencies between variables. Section 26.2 describes the basis of this option in openair plot. As an example, consider the question: what are the meteorological conditions that control high and low concentrations of PM10? By setting type = "pm10", openair will split the PM10 concentrations into four quantiles i.e. roughly equal numbers of points in each level. The plot will then show four different wind roses for each quantile level, although the default number of levels can be set by the user — see ?cutData for more details. Figure 5.3 shows the results of setting type = "pm10". For the lowest concentrations of PM10 the wind direction is dominated by northerly winds, and relatively low wind speeds. By contrast, the highest concentrations (plot furthest right) are dominated by relatively strong winds from the south-west. It is therefore very easy to obtain a good idea about the conditions that tend to lead to high (or low) concentrations of a pollutant. Furthermore, the type option is available in almost all openair functions.

windRose(mydata, type = "pm10", layout = c(4, 1))
Figure 5.3: Wind rose for four different levels of PM10 concentration. The levels are defined as the four quantiles of PM10 concentration and the ranges are shown on each of the plot labels.

A comparison of the effect that bias has can be seen by plotting the following. Note the prominent frequencies for W, E and N in particular that are due to the bias issue discussed by Applequist (2012).

Applequist, Scott. 2012. “Wind Rose Bias Correction.” Journal of Applied Meteorology and Climatology 51 (7): 1305–9.
## no bias correction
windRose(mydata, angle = 22.5, bias.corr = FALSE)

## bias correction (the default)
windRose(mydata, angle = 22.5)

pollutionRose is a variant of windRose that is useful for considering pollutant concentrations by wind direction, or more specifically the percentage time the concentration is in a particular range. This type of approach can be very informative for air pollutant species, as demonstrated by Ronald Henry and co-authors in Henry et al. (2009).

Henry, Ronald, Gary A. Norris, Ram Vedantham, and Jay R. Turner. 2009. Source Region Identification Using Kernel Smoothing.” {Article}. Environmental Science & Technology (1155 16TH ST, NW, WASHINGTON, DC 20036 USA) 43 (11): 4090–97. https://doi.org/{10.1021/es8011723}.

You can produce similar pollution roses using the pollutionRose function in recent versions of openair, e.g. as in Figure 5.4:

pollutionRose(mydata, pollutant = "nox")
Figure 5.4: NOx pollution rose produced using pollutionRose and default pollutionRose settings.

pollutionRose is wrapper for windRose. It simply replaces the wind speed data series in the supplied data set with another variable using the argument pollutant before passing that on to windRose. It also modifies breaks to estimate a sensible set of break points for that pollutant and uses a slightly different set of default options (key to right, wedge style plot) but otherwise handles arguments just like the parent windRose function.

While Figure 5.4 indicates that higher NOx concentrations are also associated with the SW, conditioning allows you to be much informative. For example, conditioning by SO2 (Figure 5.5) demonstrates that higher NOx concentrations are associated with the SW and much of the higher SO2 concentrations. However, it also highlights a notable NOx contribution from the E, most apparent at highest SO2 concentrations that is obscured in Figure 5.4 by a relatively high NOx background Figure 5.5.

pollutionRose(
  mydata,
  pollutant = "nox",
  type = "so2",
  layout = c(4, 1),
  key.position = "bottom"
)
Figure 5.5: NOx pollution rose conditioned by SO2 concentration.

pollutionRose can also usefully be used to show which wind directions dominate the overall concentrations. By supplying the option statistic = "prop.mean" (proportion contribution to the mean), a good idea can be gained as to which wind directions contribute most to overall concentrations, as well as providing information on the different concentration levels. A simple plot is shown in Figure 5.6, which clearly shows the dominance of south-westerly winds controlling the overall mean NOx concentrations at this site. Indeed, almost half the overall NOx concentration is contributed by two wind sectors to the south-west. The polarFreq function can also show this sort of information, but the pollution rose is more effective because both length and colour are used to show the contribution. These plots are very useful for understanding which wind directions control the overall mean concentrations.

pollutionRose(
  mydata,
  pollutant = "nox",
  statistic = "prop.mean"
)
Figure 5.6: Pollution rose showing which wind directions contribute most to overall mean concentrations.

It is sometimes useful to more clearly understand the contributions from wind directions that have low frequencies. For example, for a pollution rose of SO2 there are few occurrences of easterly winds making it difficult to see how the concentration intervals are made up. Try:

pollutionRose(mydata, pollutant = "so2", seg = 1)

However, each wind sector can be normalised to give a probability between 0 and 1 to help show the variation within each wind sector more clearly. An example is shown in Figure 5.7 where for easterly winds it is now clearer that a greater proportion of the time the concentration is made up of high SO2 concentrations. In this plot each wind sector is scaled between 0 and 1. Also shown with a black line is an indication of the wind direction frequency to remind us that winds from the east occur with a low frequency.

pollutionRose(
  mydata,
  pollutant = "so2",
  normalise = TRUE
)
Figure 5.7: SO2 pollution rose produced using pollutionRose normalised by each wind sector.

5.2 Comparing two meteorological data sets

The windRose function is also useful for comparing two meteorological data sets. In this case a ‘reference’ data set is compared with a second data set. There are many reasons for doing so e.g. to see how one site compares with another or for meteorological model evaluation (more on that in later sections). In this case, ws and wd are considered to the the reference data sets with which a second set of wind speed and wind directions are to be compared (ws2 and wd2).

In the next example, data from two data sets from 2024 are imported over the Internet. The first is hourly data measured data for a site in London and the second is hourly data modelled data. The data are then joined together by date to create a single data frame with the two sets of wind speed and wind direction data. A more realistic example might be to compare a modelled data set with a reference data set, but the principle is the same. Such data can be imported using the worldmet package, as described in Chapter 4.

## example of comparing 2 met sites

# london met data
london_met <- readr::read_rds(
  "https://github.com/openair-project/book/raw/refs/heads/main/assets/data/london_met.rds"
)

# data from model
mod_met <- importAURN("kc1", 2024)

# combine into one data frame and change names - only select ws, wd and date
met_compare <- inner_join(
  select(london_met, date, ws, wd),
  select(mod_met, date, ws, wd),
  suffix = c("_lon", "_yor"),
  by = "date"
)

The windRose function can then be used to compare the two data sets. In this case, the plot shown in Figure 5.8 shows the difference between the two data sets with respect to the reference data set (in this case, the London site). The colours show whether the second data set (modelled) tends to be positively or negatively biased with respect to the reference data set (measured). It shows for example:

  • Modelled wind speeds tend to be lower than at measured for wind directions from the south, shown by the blue colouring in Figure 5.8.

  • Wind speeds from the model tend to be slightly higher than measured values when the wind is from the north, shown by the red colouring in Figure 5.8.

  • Overall, the modelled wind speeds are 0.67 m s-1 lower than the measured values, shown by the text on the plot.

  • There is a bias in the wind direction of +15.9 degrees for the modelled data — shown by both the arrow on the plot and the text.

windRose(
  met_compare,
  ws = "ws_lon",
  wd = "wd_lon",
  ws2 = "ws_yor",
  wd2 = "wd_yor"
)
Figure 5.8: Wind rose showing the difference between two meteorological data sets. The first (measured) is used to compare against the second (modelled). The colours are used to show whether data tend to be positively or negatively biased with respect to the reference data set. The arrow shows the mean bias in wind direction and the text shows the value of that bias.

Like other openair functions, the type option can be used to compare the two data sets by other variables, as shown in Figure 5.9 for seasonal differences.

windRose(
  met_compare,
  ws = "ws_lon",
  wd = "wd_lon",
  ws2 = "ws_yor",
  wd2 = "wd_yor",
  type = "season"
)
Figure 5.9: Wind rose showing the difference between two meteorological data sets by season. The first (measured) is used to compare against the second (modelled). The colours are used to show whether data tend to be positively or negatively biased with respect to the reference data set. The arrows shows the mean bias in wind direction and the text shows the value of that bias.

  1. Thanks to Philippe Barneoud of Environment Canada for pointing this issue out.↩︎