首页 > 解决方案 > 如何在动画地图 R 上添加第二个点变量?

问题描述

我是 R 中动画数据的新手。我正在尝试在一张地图上使用锁定和预锁定之间的每小时读数对 2 个变量(NO2 水平和车辆编号)进行动画处理,以便按位置显示两个变量的变化(对于 3 个传感器)按 2019 年 4 月和 2020 年 4 月的日期和时间。我可以做一个变量(在代码中显示),甚至可以改变点的形状来表示高峰时段的交通),但我无法让第二个变量(车辆)工作。这个想法是为了展示在锁定期间减少流量如何降低二氧化氮水平(尽管对此的回归低于预期)。

我知道锁定的数据将与去年(闰年)相差 2 天,但这目前仅用于教学目的,所以我还没有尝试下载更多数据来尝试修复它。我想知道的是如何让车辆数据与 NO2 数据同时显示?我尝试添加另一个geom_point并稍微轻推它,以免它们重叠,但它不起作用 - 我认为我不能在一张地图上拥有 2 个 geom_points。我现在正在为车辆尝试 geom_jitter 并且可以让它改变颜色但不改变大小。似乎每张地图只能有一个 scale_size 。有没有解决的办法?

编辑用于dput添加数据并显示我尝试过的另一个示例 - 希望我现在正确。再次编辑以尝试更清晰并为有效的单个变量放置代码

structure(list(Location = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L), .Label = c("Coast_Road", "Gosforth", "TyneBridge"), class = "factor"), 
    Date = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 
    1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L), .Label = c("1/4/2019", 
    "1/4/2020", "10/4/2019", "10/4/2020", "11/4/2019", "11/4/2020", 
    "12/4/2019", "12/4/2020", "13/4/2019", "13/4/2020", "14/4/2019", 
    "14/4/2020", "15/4/2019", "15/4/2020", "16/4/2019", "16/4/2020", 
    "17/4/2019", "17/4/2020", "18/4/2019", "18/4/2020", "19/4/2019", 
    "19/4/2020", "2/4/2019", "2/4/2020", "20/4/2019", "20/4/2020", 
    "21/4/2019", "21/4/2020", "22/4/2019", "22/4/2020", "23/4/2019", 
    "23/4/2020", "24/4/2019", "24/4/2020", "25/4/2019", "25/4/2020", 
    "26/4/2019", "26/4/2020", "27/4/2019", "27/4/2020", "28/4/2019", 
    "28/4/2020", "29/4/2019", "29/4/2020", "3/4/2019", "3/4/2020", 
    "30/4/2019", "30/4/2020", "4/4/2019", "4/4/2020", "5/4/2019", 
    "5/4/2020", "6/4/2019", "6/4/2020", "7/4/2019", "7/4/2020", 
    "8/4/2019", "8/4/2020", "9/4/2019", "9/4/2020"), class = "factor"), 
    Date2 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Hour = c("04", 
    "03", "02", "01", "04", "03", "01", "02", "04", "01", "02", 
    "03", "04", "03", "02", "01", "03", "04", "02", "04", "01", 
    "03", "02", "01"), Day = structure(c(2L, 2L, 2L, 2L, 7L, 
    7L, 7L, 7L, 2L, 2L, 2L, 2L, 7L, 7L, 7L, 7L, 2L, 2L, 2L, 7L, 
    2L, 7L, 7L, 7L), .Label = c("Fri", "Mon", "Sat", "Sun", "Thurs", 
    "Tues", "wed"), class = "factor"), Lock = structure(c(2L, 
    2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 
    2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L), .Label = c("Lockdown", "PreLockdown"
    ), class = "factor"), Rush = structure(c(1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L), .Label = c("NonRushHour", "RushHour"
    ), class = "factor"), NO2 = c(27.76196, 35.78016, 45.7216, 
    22.2686, 6.23032, 5.7622, 8.53896, 11.8158, 22.16896, 28.5572, 
    24.957, 18.73608, 4.60976, 4.11532, 10.5656, 5.6024, 25.98724, 
    28.00448, 50.7224, 8.65552, 82.8046, 11.8722, 8.4506, 9.3812
    ), Vehicles = c(38L, 54L, 43L, 37L, 20L, 34L, 30L, 41L, 14L, 
    13L, 6L, 10L, 23L, 19L, 18L, 16L, 31L, 43L, 30L, 49L, 35L, 
    30L, 38L, 26L), DateTime = c(1.04, 1.03, 1.02, 1.01, 1.04, 
    1.03, 1.01, 1.02, 1.04, 1.01, 1.02, 1.03, 1.04, 1.03, 1.02, 
    1.01, 1.03, 1.04, 1.02, 1.04, 1.01, 1.03, 1.02, 1.01), Lon = c(-1.5662, 
    -1.5662, -1.5662, -1.5662, -1.5662, -1.5662, -1.5662, -1.5662, 
    -1.6199, -1.6199, -1.6199, -1.6199, -1.6199, -1.6199, -1.6199, 
    -1.6199, -1.606, -1.606, -1.606, -1.606, -1.606, -1.606, 
    -1.606, -1.606), Lat = c(54.9944, 54.9944, 54.9944, 54.9944, 
    54.9944, 54.9944, 54.9944, 54.9944, 55.0071, 55.0071, 55.0071, 
    55.0071, 55.0071, 55.0071, 55.0071, 55.0071, 54.968, 54.968, 
    54.968, 54.968, 54.968, 54.968, 54.968, 54.968)), row.names = c(1L, 
2L, 3L, 5L, 1074L, 1080L, 1331L, 1430L, 1481L, 1501L, 1502L, 
1605L, 2198L, 2202L, 2204L, 2205L, 2966L, 2968L, 2972L, 3315L, 
3340L, 3441L, 3442L, 3443L), class = "data.frame")

代码块:

library(gganimate) library(OpenStreetMap) library(ggplot2) library(maps)

#set lat and long for the size of the map (top left and bottom right coordinates)
 
LAT1 =  54.962130 ; LAT2 = 55.018427 LON1 = -1.556871 ; LON2 =
-1.652677
 
map <- openmap(c(LAT2,LON1), c(LAT1,LON2), zoom = NULL)

map.latlon <- openproj(map) 

My_Theme = theme(   plot.title = element_text(size = 30),  
legend.position = "right",    legend.text = element_text(color =
"black", size = 18),   legend.title = element_text(size = 20),  
axis.title = element_text(size = 25),   axis.text = element_text(size = 20),   strip.text = element_text(face="bold", size=25,lineheight=5.0),   strip.background =
element_rect(fill="lightblue", colour="black", size=1))

OSMap <-  OpenStreetMap::autoplot.OpenStreetMap(map.latlon)+ 
  geom_label(data=pol5, aes(x=Lon ,y=Lat, label=Location, fontface=7), hjust=1.3, vjust=0, size=7) +
  geom_point(aes(x = Lon, y = Lat, size = NO2,  shape = Rush),
             data = pol5, color="red") + 
  
  scale_size_continuous(range = c(4, 30), breaks = c(0, 50, 100, 150, 200)) +
  labs(size = 'NO2')  +
  facet_wrap(~Lock) + 
  My_Theme +   
  labs(title = "Date and Time  {closest_state}") +
  transition_states(DateTime, transition_length = 3, state_length = 1)

animate(OSMap , nframes = 100, fps=12, width = 1600, height = 1000, start_pause= 20, end_pause = 30, rewind = TRUE)

标签: ranimationmaps

解决方案


在地图上获取两个点的一种方法是旋转数据框:每个“度量”获取一行,其中“度量”是 NO2 或车辆数量。这是一张地图,红色为 NO2,蓝色为车辆;车辆向东移动一点,以免这些点重叠。

OSMap <-  OpenStreetMap::autoplot.OpenStreetMap(map.latlon) + 
  geom_label(data = pol5,
             aes(x = Lon, y = Lat, label = Location),
             fontface = 7, hjust = 1.3, vjust = 0, size = 7) +
  geom_point(data = pol5 %>%
               dplyr::select(DateTime, Lon, Lat, NO2, Vehicles, Rush, Lock) %>%
               pivot_longer(cols = c("NO2", "Vehicles"), names_to = "measure") %>%
               mutate(Lon = Lon + ifelse(measure == "Vehicles", 0.005, 0)),
             aes(x = Lon, y = Lat, color = measure, fill = measure,
                 size = value, shape = Rush)) +
  scale_size_continuous(range = c(4, 30), breaks = c(0, 50, 100, 150, 200),
                        guide = F) +
  labs(size = 'NO2 or Vehicles')  +
  facet_wrap(~ Lock) + 
  My_Theme +   
  labs(title = "Date and Time  {closest_state}") +
  transition_states(DateTime, transition_length = 3, state_length = 1)

在此处输入图像描述

您可能需要更多的修补才能获得您想要的确切行为。例如,正如您已经指出的,NO2 和车辆的比例相同是没有意义的;他们甚至不使用相同的单位。现在可以了,因为这两个度量的值恰好占据了相似的范围,但是如果您想添加其他度量,则不一定如此。我可能会通过将每个度量中的值归一化以使其落在 [0, 1] 范围内来解决问题,其中 0 表示最小的观察值,1 表示最大的值。我不确定是否可以显示具有两种不同尺寸比例的自定义图例;我知道这些事情来之不易ggplot2,按设计。如果没有,我可能会完全抑制大小比例并为点添加标签;这是可能看起来的粗略版本:

OSMap <-  OpenStreetMap::autoplot.OpenStreetMap(map.latlon) + 
  geom_label(data = pol5,
             aes(x = Lon, y = Lat, label = Location),
             fontface = 7, hjust = 1.3, vjust = 0, size = 7) +
  geom_point(data = pol5 %>%
               dplyr::select(DateTime, Lon, Lat, NO2, Vehicles, Rush, Lock) %>%
               pivot_longer(cols = c("NO2", "Vehicles"), names_to = "measure") %>%
               mutate(Lon = Lon + ifelse(measure == "Vehicles", 0.005, 0)),
             aes(x = Lon, y = Lat, color = measure, fill = measure,
                 size = value, shape = Rush)) +
  geom_text(data = pol5 %>%
              dplyr::select(DateTime, Lon, Lat, NO2, Vehicles, Rush, Lock) %>%
              pivot_longer(cols = c("NO2", "Vehicles"), names_to = "measure") %>%
              mutate(Lon = Lon + ifelse(measure == "Vehicles", 0.005, 0),
                     value = round(value)),
            aes(x = Lon, y = Lat, label = value)) +
  scale_size_continuous(range = c(4, 30), breaks = c(0, 50, 100, 150, 200),
                        guide = F) +
  facet_wrap(~ Lock) + 
  My_Theme +   
  labs(title = "Date and Time  {closest_state}") +
  transition_states(DateTime, transition_length = 3, state_length = 1)

在此处输入图像描述


推荐阅读