下午好,
我正在尝试制作一个时间序列图,箭头显示风向,并着色显示风速强度。最终我试图得到这样的情节(只是我在网上找到的一个示例图片):
我设法找到了一个类似的帖子(见下文),我试图遵循,但我坚持正确显示风向箭头。
上一篇类似文章: ggplot2 wind time series with arrows/vectors
我到目前为止所编制的代码如下:
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()
使用上面的代码我得到以下图:
正如你所看到的那样,情节开始了我希望它开始的箭头,但方向和终点太长了,我不知道如何将它缩放成一个颜色编码为速度的较短箭头。我非常感谢您对我如何实现这一目标的任何指导。
非常感谢, 阿燕
答案 0 :(得分:4)
您在上面显示的图表没有给出正确的指示 - 例如dat$wd[1]
约为190°,因此如果0°对应于右侧的水平箭头,则190°会给出一个向左和向下的箭头。
要获得正确方向的箭头,您需要将风向的余弦和正弦添加到箭头的起点以定义其终点(请参阅下面的代码)。这里的难点是箭头在x和y方向上的缩放,因为(1)这些轴是完全不同的尺度,因此箭头的“长度”实际上并不意味着任何东西和(2)你的纵横比绘图设备会扭曲箭头的视觉长度。
我在下面发布了一个解决方案草图,其中我将箭头在x和y方向上的偏移量缩放了用于绘图的变量范围的10%,但是这不会产生具有统一视觉长度的矢量。在任何情况下,这些箭头的长度都没有很好地定义,因为,(a)x轴和y轴代表不同的单位,(b)改变曲线的纵横比将改变这些箭头的长度。
## 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")
答案 1 :(得分:3)
这还不完整,但我希望这对您或其他人来说都是一个开始。我能正确理解以下内容吗?
如果是这样,一个缺失的部分是从极坐标转换为笛卡尔坐标。 (例如,http://www.engineeringtoolbox.com/converting-cartesian-polar-coordinates-d_1347.html)
坐标系是我遗漏的缺失部分。该图是两个坐标系的混合。箭头的起点基于(时间x污染物)。但是矢量是方向和风速的极坐标。假设(时间x污染物)的长宽比不是1,那么来自北方的5knot微风将具有与来自东南方的5knot微风不同的长度。
必须调整两件事。一个是(时间x污染物)纵横比。另一个是图的物理尺寸。我不知道如何处理第二个,所以我把它固定为一个恒定的值。但是想象一下你会想要一些更好的方法 - 可能是通过查询一些底层的网格属性。
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()
答案 2 :(得分:0)
使用十进制度计算风的方向。假设您希望0度为北(向上),请使用以下内容:
ggplot(data = dat, aes(x=datetime, y=pollutant)) +
geom_text(aes(angle=-wd_degrees+90), label="→")
答案 3 :(得分:0)
我想知道其他目标相似的人是否会发现OpenAir中的以下功能有用。它基本上完全按照问题的要求进行操作,唯一的例外是它没有专门使用ggplot2(在标题中提到但并未真正指定为问题的要求)。我花了很多时间寻找一个简单的解决方案,最终偶然发现了OpenAir的“风向图”,早在2015年在以下时事通讯中宣布:
https://rstudio-pubs-static.s3.amazonaws.com/94224_992de57be72e455e8ce13386dfd9a932.html
示例代码:
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")