如何在R中的极坐标系中添加时间维度?

8
我正在尝试使用ggplot2绘制一只鸟在南极周围的轨迹。到目前为止,我得到了一个投影在极坐标上的地图,我还成功地正确绘制了轨迹点,并且几乎正确链接它们,但是……随着轨迹穿过国际日期和时间线ggplot2无法正确地链接该线两侧的2个点。因此,我正在寻找一种方法强制ggplot以连续方式连接这些点。

这是我的数据集:

Data =>
ID  Date      Time   A1   Lat.    Long.
10 12.9.2008 22:00   1  21.14092 70.98817 
10 12.9.2008 22:20   1  21.13031 70.97592 
10 12.9.2008 22:40   2  21.13522 70.97853 
10 12.9.2008 23:00   1  21.13731 70.97817
10 12.9.2008 23:20   3  21.14197 70.97981
10 12.9.2008 23:40   1  21.14156 70.98158
10 12.9.2008 23:40   1  21.14156 70.98158
10 13.9.2008 00:00   2  21.14150 70.98478
10 13.9.2008 00:20   3  21.14117 70.98803
10 13.9.2008 00:40   1  21.14117 70.98803
10 13.9.2008 01:00   2  21.14117 70.98803

....

ID是鸟的身份证号码。

使用Nick K代码进行更新

这是我的原始图表,没有使用时间维度和线条。

south_map <- map_data("world") %>% group_by(group) 
set.seed(123)

track_df2 <- new_df2

long_diff <- diff(new_df2$Long)
long_diff[long_diff < -180] <- long_diff[long_diff < -180] + 360
long_diff[long_diff > 180] <- long_diff[long_diff > 180] - 360
track_df2$Longitude <- cumsum(c(new_df2$Long[1], long_diff))

ggplot(track_df2, aes(x = track_df2$Long, y = track_df2$Lat)) +
geom_polygon(aes(group = a3_id), data = south_map, colour = "grey", fill = "gainsboro") +
geom_point(aes(colour = factor(a3_id)), size = 2)

A1定义了鸟目前正在做的事情。

enter image description here


1
只需根据排序后的时间连接这些点即可? - Vlo
1
同意@Vlo的观点,我认为你只需要转换时间。不错的问题。 - Liz Young
1
@VIo,我没听懂你的意思。你能给我举个例子或者解释一下吗? - ayush
3
不建议通过电子邮件联系软件包维护者,Stack Overflow是这类问题的一个好论坛,但ggplot Google组也是另一个选择。要获得答案,您可以制作一个小的可重现示例。您可以分享一个数据集,但不提供用于绘图的代码,然后展示另一个数据集的绘图代码。让我们看看该数据及其图形代码,并使用dput()共享数据以便复现。 - Gregor Thomas
1
@ayush,你还没有使用dput分享数据。请参考这个问题及其答案 - akhmed
显示剩余8条评论
1个回答

14

你似乎没有在你的图中实际使用时间,但问题在于经度绕过-180/180。这可以通过使用coord_map而不是coord_polar来解决,并确保经度不会绕过。

加载包并生成样本数据

library("ggplot2")
library("dplyr")
south_map <- map_data("world") %>% group_by(group) %>% filter(min(lat) <= -20)

set.seed(123)
track <- data.frame(long = cumsum(c(210,
                                    unlist(lapply(c(1, -1), function(x) {
                                      rnorm(50, x * 4, 4)
                                      })))) %% 360 - 180,
                    lat = cumsum(c(-50, rnorm(100, 0.4, 2))),
                    A1 = sample(1:3, 101, replace = TRUE))

确保坐标不会环绕:

track_new <- track
long_diff <- diff(track$long)
long_diff[long_diff < -180] <- long_diff[long_diff < -180] + 360
long_diff[long_diff > 180] <- long_diff[long_diff > 180] - 360
track_new$long <- cumsum(c(track$long[1], long_diff))

使用等距方位投影进行绘图。请注意,这假定北极位于中心,因此纬度被翻转并通过比例尺进行校正。

ggplot(track_new, aes(x = long, y = -lat)) +
  geom_polygon(aes(group = group), data = south_map, colour = "grey", fill = "gainsboro") +
  coord_map("azequidistant") +
  geom_point(aes(colour = factor(A1)), size = 2) +
  geom_path(colour = "grey", size = 1) +
  scale_x_continuous(breaks = NULL) +
  scale_y_continuous("latitude", breaks = 25 * 0:3, labels = -25 * 0:3)

最终的图表:

鸟类图表

仅供趣味,我认为制作这张图片的动画会很有趣。以下是实现它的代码:

track_new$alpha <- 1
# Setup longitude labels

long_labels <- data.frame(long = 45 * -3:4, lat = -22.5)
long_labels$label <- long_labels$long
long_labels$label[8] <- "\U00B1 180"
long_labels$angle <- long_labels$long + 67.5 + 180 * (long_labels$long >= 45)

# Set up the basic plot
p <- ggplot(track_new, aes(x = long, y = -lat)) +
  geom_polygon(aes(group = group), data = south_map, colour = "grey", fill = "gainsboro") +
  coord_map("azequidistant", ylim = c(20, 90)) +
  geom_point(aes(colour = A1, alpha = alpha), size = 2) +
  geom_path(aes(alpha = alpha), colour = "grey", size = 1) +
  scale_x_continuous(breaks = NULL) +
  scale_y_continuous("latitude", breaks = 22.5 * 0:3, labels = -22.5 * 0:3) +
  scale_alpha_identity(guide = "none") +
  geom_text(aes(label = label, angle = angle),
            data = long_labels, colour = "dark blue", alpha = 0.5, size = 4)

# Produce the animation
p$data$alpha <- 0
for(i in 1:(nrow(track_new) + 10)) {
  p$data$alpha <- pmax(p$data$alpha - 0.1, 0)
  if (i <= nrow(track_new)) {
    p$data$alpha[i] <- 1
  }
  png(file.path("BirdPlots", sprintf("BirdPlot%03d.png", i)), width = 1024, height = 1024, res = 100)
  print(p)
  dev.off()
  if (!(i %% 5)) cat(i, "\n")
}

# This needs ImageMagick in the system path. For non-Windows systems, you
# might be better using system rather than shell
shell(paste("convert", file.path("BirdPlots", "BirdPlot*.png"),
  file.path("BirdPlots", "BirdPlotAnimation.gif")))

这是结果:

鸟的动画

编辑 ayush 代码的已更正版本

track_df2 <- new_df2

long_diff <- diff(new_df2$Longitude)
long_diff[long_diff < -180] <- long_diff[long_diff < -180] + 360
long_diff[long_diff > 180] <- long_diff[long_diff > 180] - 360
track_df2$Longitude <- cumsum(c(new_df2$Longitude[1], long_diff))

track_df2$a3_id <- factor(track_df2$a3_id)

ggplot(track_df2, aes(x = Longitude, y = -Latitude)) +
  coord_map("azequidistant", ylim = c(20, 90)) +
  geom_point(aes(colour = a3_id, alpha = alpha), size = 2) +
  geom_path(aes(alpha = alpha), colour = "grey", size = 1) +
  scale_x_continuous(breaks = NULL) +
  scale_y_continuous(breaks = 22.5 * 0:3, labels = -22.5 * 0:3) +
  scale_alpha_identity(guide = "none")

我已经添加了一个动画版本,它会生成一系列PNG文件并将它们转换为动态GIF。 - Nick Kennedy
@ayush 我不太确定你的意思。你想要一个有效的三维散点图,时间表示为高度吗?还是其他什么?你到目前为止尝试了什么?值得注意的是,你的原始数据都在70.9到71度经度之间,所以你得到的极地投影看起来完全不对。 - Nick Kennedy
我想通过绘图来测量的是,我想看看在什么时间我的纬度和经度是什么?同时,我也想在同一张图表中分析鸟的路径(就像你所做的那样)。你能帮忙这个部分吗? 你的动画图对我非常有帮助。 非常感谢。 - ayush
@ayush,您希望在图表上打印时间标签还是制作3D图形?如果是前者,则可以直接使用geom_text打印时间。对于后者,建议使用plot3d。另一个选项是创建一个实际上是加速的实时动画,并能够逐步浏览它。 - Nick Kennedy
2
Alpha 表示透明度。如果将其设置为零,则不会绘制任何内容。然后,使用我上面发布的循环来依次设置每个点的 alpha 并生成图像的想法。然后可以将这些图像转换为动画(使用 ImageMagick)或电影(使用 ffmpeg)。如果您想查看所有点,请将 p$data$alpha <- 1 设为 1。 - Nick Kennedy
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接