6

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.

Community
  • 1
  • 1
redbaron1981
  • 407
  • 3
  • 9

2 Answers2

4

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="→")
Brian D
  • 2,570
  • 1
  • 24
  • 43
  • Hi Brian, thanks for the help I will give it a try. I am really surprised that there is not an arrow plotting function in R, where arrows can be drawn of fixed length and a given angle with out having to use coordinates. – redbaron1981 Mar 12 '17 at 18:12
  • The problem from what I can see is that geom_spoke & geom_segment require x,y,xend,yend args to draw the segments. With the above data we are mixing the units between time series and metres. x & xend being in time units and y &y end being in metres. Its this what I think is screwing up the function because the scale is incorrect. Because of this the actual direction of the arrows can be incorrect. What I would like is an arrow where I can use a vector for centre point values and use an angle vector to specify the the direction the angle points. This would then fix the scaling issues. – redbaron1981 Mar 12 '17 at 21:04
  • The "trick" with geom_text and an arrow is really neat! There is no problem with differing units for time and a y-variable then. – Phann Sep 06 '21 at 09:51
0

If you have compass degrees, so it's starts at the north and the direction going clockwise, the conversion from degrees to radius doesn't work. To convert it to radius you need to do this:

degree_bearing <- (450 - bearing) %% 360 
radius <-  degree_bearing* pi / 180

Then you will have the correct radius.

Marinka
  • 1,189
  • 2
  • 11
  • 24