Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Plotting swell direction arrows with ggplot2 geom_spoke

Tags:

r

ggplot2

I am trying to plot swell direction(md$Swell.Dir and height(md$m) so that the result is a graph similar to the below;

WindDirection&WaveHeight

Here is a small sample of my data using dput;

md <- structure(list(UTC = structure(1:6, .Label = c("01-Feb-17 1200", 
"01-Feb-17 1500", "01-Feb-17 1800", "01-Feb-17 2100", "02-Feb-17 0000", 
"02-Feb-17 0300", "02-Feb-17 0600", "02-Feb-17 0900", "02-Feb-17 1200", 
"02-Feb-17 1500", "02-Feb-17 1800", "02-Feb-17 2100", "03-Feb-17 0000", 
"03-Feb-17 0300", "03-Feb-17 0600", "03-Feb-17 0900", "03-Feb-17 1200", 
"03-Feb-17 1500", "03-Feb-17 1800", "03-Feb-17 2100", "04-Feb-17 0000", 
"04-Feb-17 0300", "04-Feb-17 0600", "04-Feb-17 0900", "04-Feb-17 1200", 
"04-Feb-17 1500", "04-Feb-17 1800", "04-Feb-17 2100", "05-Feb-17 0000", 
"05-Feb-17 0300", "05-Feb-17 0600", "05-Feb-17 0900", "05-Feb-17 1200", 
"05-Feb-17 1500", "05-Feb-17 1800", "05-Feb-17 2100", "06-Feb-17 0000", 
"06-Feb-17 0300", "06-Feb-17 0600", "06-Feb-17 0900", "06-Feb-17 1200", 
"06-Feb-17 1500", "06-Feb-17 1800", "06-Feb-17 2100", "07-Feb-17 0000", 
"07-Feb-17 0300", "07-Feb-17 0600", "07-Feb-17 0900", "07-Feb-17 1200", 
"07-Feb-17 1500", "07-Feb-17 1800", "07-Feb-17 2100", "08-Feb-17 0000", 
"08-Feb-17 0300", "08-Feb-17 0600", "08-Feb-17 0900", "08-Feb-17 1200", 
"08-Feb-17 1500", "08-Feb-17 1800", "08-Feb-17 2100", "09-Feb-17 0000"
), class = "factor"), SigWave.m = c(1.7, 1.7, 1.6, 1.6, 1.7, 
1.8), WindWave.Dir = c(140L, 141L, 142L, 180L, 150L, 150L), Metres = c(1.7, 
1.7, 1.6, 1.6, 1.7, 1.7), WindWave.s = c(5.8, 5.7, 5.7, 5.5, 
5.4, 5.4), Swell.Dir = c(17L, 18L, 24L, 11L, 12L, 12L), m = c(0.5, 
0.5, 0.5, 0.3, 0.2, 0.2), Wave1.Dir = c(137L, 137L, 137L, 137L, 
141L, 143L)), .Names = c("UTC", "SigWave.m", "WindWave.Dir", 
"Metres", "WindWave.s", "Swell.Dir", "m", "Wave1.Dir"), row.names = c(NA, 
6L), class = "data.frame")

Firstly I change the date to the correct format with;

md$UTC <-as.POSIXct(md$UTC, format = "%d-%b-%y %H%M")

According to geom_spoke package;

"This is a polar parameterisation of geom_segment. It is useful when you have >variables that describe direction and distance."

Since my swell directions are polarised I believe geom_spoke to be the correct geom function to use. However the code below doesn't give me the desired outcome and the spokes have no polarised direction.

ggplot(data = md) + geom_spoke(mapping = aes(x = UTC, y = m, angle = Swell.Dir, radius = 0.5 ))

Here is the output from geom_spoke function.

geom_spoke output

I have read similar problems on these links here, here and here but trying the suggested solutions did not give me the desired outcome. I think that my problem might be in how ggplot computes the xend yend arguments for the geom_segment function but I found a way get around this.

Thanks for your help.

like image 646
redbaron1981 Avatar asked Mar 12 '17 14:03

redbaron1981


1 Answers

Take a look at the example here: http://docs.ggplot2.org/current/geom_spoke.html

There are a few things that you'll want to modify.

  1. How you define the angle.
    The angle right now, I assume, is defined in degrees where 0 degrees would be straight up (North). However, the geom_spoke() code uses the sin() and cos() functions in which the angle is defined in radians.
    Per the example, straight to the right (East) is 0 or 2*pi, straight up (North) is pi/2, left (West) is pi, down (South) is pi*1.5, etc. So you need to convert your degrees into the appropriate units. (i.e. ((-degrees+90)/360)*2*pi)

  2. How you define the radius.
    The way the radius displays depends upon the units of the x and y axes. See: https://github.com/tidyverse/ggplot2/blob/master/R/geom-spoke.r It would work best if both the x and the y axes were defined in the same units as that is the assumption of the function's math.

If you really want to use geom_spoke(), then the following code will get you most of the way there, but know that the angle will not be accurate until you convert both axes to the same units:

library(ggplot2)

md <- data.frame(UTC = c("01-Feb-17 1200", "01-Feb-17 1500", "01-Feb-17 1800", "01-Feb-17 2100", "02-Feb-17 0000", "02-Feb-17 0300"), 
                 SigWave.m = c(1.7, 1.7, 1.6, 1.6, 1.7, 1.8), 
                 WindWave.Dir = c(140L, 141L, 142L, 180L, 150L, 150L), 
                 Metres = c(1.7, 1.7, 1.6, 1.6, 1.7, 1.7), 
                 WindWave.s = c(5.8, 5.7, 5.7, 5.5, 5.4, 5.4), 
                 Swell.Dir = c(17L, 18L, 24L, 11L, 12L, 12L), 
                 m = c(0.5, 0.5, 0.5, 0.3, 0.2, 0.2), 
                 Wave1.Dir = c(137L, 137L, 137L, 137L, 141L, 143L))

md$newdir <- ((-md$Swell.Dir+90)/360)*2*pi

ggplot(data = md, aes(x=UTC, y=m)) + 
  geom_point() + 
  geom_spoke(aes(angle=newdir), radius=0.05 )

If you are open to an alternative to geom_spoke(), then you can use geom_text() with an ANSI (unicode) arrow symbol to get the desired output:

ggplot(data = md, aes(x=UTC, y=m)) + 
  geom_text(aes(angle=-Swell.Dir+90), label="→")
like image 184
Brian D Avatar answered Nov 06 '22 06:11

Brian D