Ggplot2 time series chart with colored wind direction arrows

Good afternoon,

I am trying to create a time series graph with arrows showing the direction of the wind and color to show the strength of the wind speed. Ultimately, I try to get a plot like this (just an example I found online):

enter image description here

I managed to find a similar post (see below), and I tried to follow, but I was right on the display of the wind direction arrows.

Previous similar entry: ggplot2 series of wind time with arrows / vectors

The codes I have collected so far are as follows:

require(ggplot2) require(scales) require(gridExtra) require(lubridate) dat <- data.frame(datetime = ISOdatetime(2013,08,04,0,0,0) + seq(0:23)*60*60, pollutant = runif(24, 25, 75)) ## create wind speed data dat$ws <- runif(nrow(dat), 0 , 15 ) ## create wind direction data dat$wd <- runif(nrow(dat), 0 , 360 ) # define an end point for geom_segment dat$x.end <- dat$datetime + minutes(60) ggplot(data = dat, aes(x = datetime, y = pollutant)) + geom_line() + geom_segment(data = dat, size = 1, aes(x = datetime, xend = x.end, y = pollutant, yend = wd), arrow = arrow(length = unit(0.5, "cm"))) + theme() 

Using the code above, I get the following graph: enter image description here

As you can see, the graph starts the arrow where I would like it to start, but the direction and end point are too long, and I'm not sure how I can scale it to be a shorter color-coded arrow for speed. I would really appreciate your attitude on how I can achieve this.

Thank you very much, ayan

+6
source share
4 answers

The plot that you show above does not give the right directions - for example. dat$wd[1] is around 190 Β°, so if 0 Β° corresponds to a horizontal right arrow, 190 Β° should give you an arrow pointing left and slightly down.

To get the arrows in the right direction, you need to add the cosine and sine of the wind direction to the start point of the arrow to determine its end point (see code below). The difficult problem here is scaling the arrows in the x and y direction, because (1) these axes are on completely different scales, so the β€œlength” of the arrow cannot mean anything and (2) the aspect ratio of your plotter will distort the visual lengths of the arrows.

I placed the solution sketch below, where I scale the arrow offset in the x and y direction by 10% of the range of variables used to plot the graph, but this does not give vectors of uniform visual length. In any case, the length of these arrows is not well defined, because, again, (a) the x and y axes represent different units and (b) changing the aspect ratio of the graph will change the length of these arrows.

 ## arrows go from (datetime, pollutant) to ## (datetime, pollutant) + scaling*(sin(wd), cos(wd)) scaling <- c(as.numeric(diff(range(dat$datetime)))*60*60, # convert to seconds diff(range(dat$pollutant)))/10 dat <- within(dat, { x.end <- datetime + scaling[1] * cos(wd / 180 * pi) y.end <- pollutant + scaling[2] * sin(wd / 180 * pi) }) ggplot(data = dat, aes(x = datetime, y = pollutant)) + geom_line() + geom_segment(data = dat, size = 1, aes(x = datetime, xend = x.end, y = pollutant, yend = y.end, colour=ws), arrow = arrow(length = unit(0.1, "cm"))) + scale_colour_gradient(low="green", high="red") 

fMSdFOY.png

And the change in aspect ratio: nOSt7B9.png

+4
source

This is not complete, but I hope this will be the beginning for you or for someone else. Do I understand the following correctly:

  • Arrow x start - time
  • The arrow starting with y is the pollutant.
  • Arrow length - wind speed
  • Arrow Orientation - Direction
  • Arrow color - wind speed

If so, one missing part is converted from polar coordinates to Cartesian coordinates. (e.g. http://www.engineeringtoolbox.com/converting-cartesian-polar-coordinates-d_1347.html )

The coordinate system is the missing part that I did not understand. This graph is a combination of two coordinate systems. The starting point of the arrow is based on (time x). But the vector is the polar coordinate of the direction and speed of the wind. Assuming that the aspect ratio (time plunge x) is not 1, then a wind of 5 knots from the north will have different lengths than a 5-fold wind from the southeast.

Two things need to be set up. One of them is the aspect ratio (time x pollutants). Another is the physical dimensions of the graph. I am not sure how to deal with the second, so I fixed it to a constant value. But imagine that you want to make some way to do it better - perhaps by requesting some basic grid property.

 dat <- data.frame( datetime = 0:100, #datetime = ISOdatetime(2013,08,04,0,0,0) + seq(0:23)*60*60, pollutant = 0 #Swap the next two lines for a nonuniform pollutant #pollutant = runif(24, 25, 75) ) ## convert to a numeric variable # dat$datetime <- 0 # dat$datetime <- as.numeric(dat$datetime) #Adjust the aspect ratio # xrange <- range(dat$datetime) xlimits <- c(-5, 100) xrange <- diff(range(xlimits)) ylimits <- c(-5, 10) yrange <- diff(range(ylimits)) aspectratio <- xrange/yrange ## create wind speed data dat$ws <- 1 # dat$ws <- runif(nrow(dat), 0, 15) ## create wind direction data #dat$wd_degrees <- runif(nrow(dat), 0, 360) dat$wd_degrees <- seq(from=0, to=360, length.out=nrow(dat)) dat$wd_radians <- dat$wd_degrees * (pi/180) ## convert from polar to cartesian dat$xend <- aspectratio * (dat$ws * sin(dat$wd_radians)) + dat$datetime dat$yend <- aspectratio * (dat$ws * cos(dat$wd_radians)) + dat$pollutant ggplot(data = dat, aes(x = datetime, y = pollutant)) + geom_line() + geom_segment(data = dat, size = 1, aes(xend = xend, yend = yend, color = ws), arrow = arrow(length = unit(0.5, "cm"))) + coord_fixed(xlim=xlimits, ylim=ylimits, ratio=1) + theme() 
+3
source

Calculate the wind direction using decimal degrees. Assuming you want 0 degrees north (up), use the following:

 ggplot(data = dat, aes(x=datetime, y=pollutant)) + geom_text(aes(angle=-wd_degrees+90), label="β†’") 
0
source

I wonder if other people with a similar purpose will find the following useful function in OpenAir. It basically does exactly what the question asks, the only exception is that it does not use ggplot2 (which is mentioned in the header, but is not really listed as a requirement in the question). I spent quite a bit of time looking for a simple solution for this and eventually came across the "wind flow graphs" in OpenAir, which was announced in 2015 in the next release:

https://rstudio-pubs-static.s3.amazonaws.com/94224_992de57be72e455e8ce13386dfd9a932.html

Code example:

 library(dplyr) library(lubridate) library(openair) # using the data from the question above: dat <- data.frame(date = ISOdatetime(2013,08,04,0,0,0) + seq(0:23)*60*60, pollutant = runif(24, 25, 75)) ## create wind speed data dat$ws <- runif(nrow(dat), 0 , 15 ) ## create wind direction data dat$wd <- runif(nrow(dat), 0 , 360 ) timePlot(dat, pollutant = "pollutant", windflow = list(scale = 0.1, lwd = 2, col = "orange"), lwd = 3, group = FALSE, ylab = "Concentration") 

wind flow

0
source

All Articles