Wind Vectors Explained

On this page

Problem statement

Wind is a vector: it has a size and a direction, and it can be written either as speed and direction or as two components, east and north. The two forms carry the same information and behave completely differently in calculations. Components add, average and interpolate like ordinary numbers; speed and direction do not, because direction lives on a circle and speed loses the sign. Most errors with wind data, from averaged directions to arrows that point the wrong way, come from doing arithmetic in the wrong form.

This page explains the two forms and the conventions that connect them, using the hourly winds reported at Tampa International Airport as Hurricane Helene passed to the west on 26–27 September 2024.

Quick answer

Convert reports to components once, and do every calculation on the components:

T["u"] = -T.speed * np.sin(np.radians(T.dir))                  # towards the east, m/s
T["v"] = -T.speed * np.cos(np.radians(T.dir))                  # towards the north, m/s
print(T[["time", "dir", "speed", "u", "v"]].iloc[::6].round(1).to_string(index=False))
print(f"mean speed {T.speed.mean():.1f} m/s; length of the mean vector {np.hypot(T.u.mean(), T.v.mean()):.1f} m/s")
               time   dir  speed    u    v
2024-09-26 06:53:00 110.0    4.1 -3.9  1.4
2024-09-26 13:53:00 130.0    6.7 -5.1  4.3
2024-09-26 19:53:00 140.0   11.3 -7.3  8.7
2024-09-27 01:53:00 180.0   17.5 -0.0 17.5
2024-09-27 07:53:00 230.0    7.7  5.9  4.9
mean speed 8.9 m/s; length of the mean vector 6.8 m/s
Hodograph of Tampa's hourly wind as Helene passed, u towards east against v towards north, points coloured by time: starting at u minus 3.9, v 1.4 on 26 September 06:53 UTC from 110 degrees, the tip climbs to u 0, v 17.5 at 01:53 UTC on the 27th from due south, then swings to positive u, ending at 11:53 UTC from 240 degrees at 6.2 metres per second. Hodograph of Tampa's hourly wind as Helene passed, u towards east against v towards north, points coloured by time: starting at u minus 3.9, v 1.4 on 26 September 06:53 UTC from 110 degrees, the tip climbs to u 0, v 17.5 at 01:53 UTC on the 27th from due south, then swings to positive u, ending at 11:53 UTC from 240 degrees at 6.2 metres per second.
The wind's vector, hour by hour.

The direction convention, veering and backing, vector changes

1. The direction convention

Meteorological wind direction is where the wind comes from, measured clockwise from north. A southerly at 180Β° blows towards the north, so its v is positive. The minus signs in the conversion turn "from" into "towards":

south = T.loc[T.dir == 180].iloc[0]
print(f"{south.time:%d %H:%M} UTC: from {south.dir:.0f}Β° at {south.speed} m/s β†’ u = {south.u:+.1f}, v = {south.v:+.1f} (blowing north)")
27 01:53 UTC: from 180Β° at 17.5 m/s β†’ u = -0.0, v = +17.5 (blowing north)

2. Veering and backing

As a storm passes, the wind turns. Turning clockwise, from east through south to west, is veering; anticlockwise is backing. In the Northern Hemisphere a station on the right of a cyclone's track sees the wind veer:

turn = (T.dir.diff() + 180) % 360 - 180
print(f"total turn over {len(T)} hours: {turn.sum():+.0f}Β° (positive = clockwise, veering); "
      f"from {T.dir.iloc[0]:.0f}Β° to {T.dir.iloc[-1]:.0f}Β°")
peak = T.loc[T.speed.idxmax()]
print(f"strongest report {peak.speed} m/s from {peak.dir:.0f}Β° at {peak.time:%d %H:%M} UTC")
total turn over 29 hours: +130Β° (positive = clockwise, veering); from 110Β° to 240Β°
strongest report 17.5 m/s from 180Β° at 27 01:53 UTC
Time series from 26 September 06 UTC to 27 September 12 UTC of Tampa's wind direction, rising steadily from east-south-east at 110 degrees through south at 01:53 UTC to south-west at 240 degrees, and wind speed as bars, peaking at 17.5 metres per second when the wind was from the south. Time series from 26 September 06 UTC to 27 September 12 UTC of Tampa's wind direction, rising steadily from east-south-east at 110 degrees through south at 01:53 UTC to south-west at 240 degrees, and wind speed as bars, peaking at 17.5 metres per second when the wind was from the south.
Veering: a clockwise turn of 130 degrees.

3. Changes are vectors too

The change in wind from one hour to the next is the difference of the vectors, not the difference of speeds. A wind that turns without strengthening has changed:

dv = np.hypot(T.u.diff(), T.v.diff())
dspeed = T.speed.diff().abs()
i = dv.idxmax()
print(f"largest hourly change: {dv[i]:.1f} m/s as a vector, {dspeed[i]:.1f} m/s in speed, at {T.time[i]:%d %H:%M} UTC")
largest hourly change: 4.2 m/s as a vector, 3.1 m/s in speed, at 27 01:53 UTC

Back to speed and direction

The data used on this page

NOAA's Integrated Surface Database, routine hourly reports (FM-15) from Tampa International Airport (station 722110-12842) from 06 UTC on 26 September to 12 UTC on 27 September 2024; speeds are converted from tenths of a metre per second.

from pathlib import Path

import numpy as np
import pandas as pd
import requests

Path("data").mkdir(exist_ok=True)
F = Path("data/72211012842.csv")
if not F.exists():
    F.write_bytes(requests.get("https://noaa-global-hourly-pds.s3.amazonaws.com/2024/72211012842.csv", timeout=300).content)
d = pd.read_csv(F, usecols=["DATE", "REPORT_TYPE", "WND"], dtype=str)
d = d[d.REPORT_TYPE.str.strip() == "FM-15"]
w = d.WND.str.split(",", expand=True)
T = pd.DataFrame({"time": pd.to_datetime(d.DATE), "dir": pd.to_numeric(w[0].replace("999", np.nan)),
                  "speed": pd.to_numeric(w[3].replace("9999", np.nan)) / 10})
T = T[(T.time >= "2024-09-26 06:00") & (T.time <= "2024-09-27 12:00")].dropna().reset_index(drop=True)
print(f"{len(T)} hourly reports from Tampa, {T.time.min():%d %H:%M} to {T.time.max():%d %H:%M} UTC")
29 hourly reports from Tampa, 26 06:53 to 27 11:53 UTC

Example 1: back to speed and direction

The components go back to the reported values exactly, the check that the signs are right:

back_dir = np.degrees(np.arctan2(-T.u, -T.v)) % 360
back_speed = np.hypot(T.u, T.v)
print(f"largest round-trip difference: direction {np.abs((back_dir - T.dir + 180) % 360 - 180).max():.1e}Β°, "
      f"speed {np.abs(back_speed - T.speed).max():.1e} m/s")
largest round-trip difference: direction 2.8e-14Β°, speed 1.8e-15 m/s

Components are natural for physics and computing

The two forms of a wind vector: components and speed with direction. one wind, two formsComponents u, vtowards east, towards northadd, average, interpolatewhat models storeTampa 01:53Z: u = 0.0, v = +17.5Speed and directionhow fast, and from wheredirection lives on a circlewhat stations reportTampa 01:53Z: 17.5 m/s from 180Β°u = βˆ’sΒ·sin(d), v = βˆ’sΒ·cos(d); d = atan2(βˆ’u, βˆ’v): exact both ways spatialworkflow.io
One wind, two forms.

The component form is the natural one for physics and computing. Newton's laws act on vectors, models integrate u and v, and any linear operation, from averaging to interpolation to differencing, works on each component separately. The speed-and-direction form is the natural one for people: it is what a weather vane and an anemometer measure, and what a forecast says. The conversion between them is exact, as long as the conventions are respected: east and north for the components, "from" and clockwise from north for the direction.

Three facts follow. The average wind over a period is the average of the components, and its length is never more than the average speed; the gap measures how much the direction varied. A change in wind is a vector difference, so a wind can change a lot without changing speed. And components belong to a coordinate system: on a rotated or projected grid, u and v follow the grid's axes and must be rotated before they mean east and north.

Calm, oceanographic conventions and height

Working with wind vectors: problems and fixes. wind vector trapsTrapInsteadarithmetic on directionscomponents: mean 6.8 m/s, not 8.9change measured as speed changevector difference: 4.2, not 3.1"from" read as "towards"southerly: v = +17.5, blowingnorthgrid components read as east/northrotate grid-relative winds firstTampa International, Helene, 26–27 September 2024 spatialworkflow.io
Wind vector traps.
  • Calm: a calm wind has components (0, 0) and no direction.
  • Oceanography: currents are named for the direction they flow towards; the same formula without the minus signs.
  • Units: knots, m/s and km/h scale both components alike; direction is unaffected.
  • Height: wind is quoted at a height, usually 10 m; speeds increase with height and directions veer in the boundary layer.
  • Grid-relative components: HRRR and other regional models store u and v along their grid.

FAQ

What are u and v wind components?

u is the part of the wind blowing towards the east and v the part blowing towards the north, both in metres per second.

Is wind direction where the wind comes from or goes to?

Where it comes from: a southerly wind blows from the south, at 180Β°.

What do veering and backing mean?

Veering is the wind turning clockwise, for example from east to south; backing is turning anticlockwise.

Why use components instead of speed and direction?

Components can be averaged, interpolated and differenced directly; speed and direction cannot.