ggplot-面板边框交替的黑色和白色矩形

时间:2019-02-25 14:16:11

标签: r ggplot2

使用ggplot,有没有办法设置黑白矩形交替的面板边框,像这样:

enter image description here

1 个答案:

答案 0 :(得分:7)

这很长,但是这里是制作边框的方法。您可以重用此代码,而不必在不同的地图之间进行重大更改,只需更新您定义的最小,最大和纬度和经度间隔的值即可。

require(ggplot2)
require(maps)

world <- map_data("world2") #get map data

首先,定义纬度和经度的最小,最大和网格间隔。这些数字将用于为边框网格矩形创建数据框,并在绘图中创建轴断点和界限。

min.lat <- -40
max.lat <- 40
interval.lat <- 20
min.long <- 0
max.long <- 90
interval.long <- 30

接下来,创建两个数据框,其中包含将形成网格的矩形的坐标,一个数据框用于黑色矩形,一个数据框用于白色矩形。为每种网格矩形颜色创建了单独的数据框,因此您无需使用scale_fill_manual()进行边界网格填充,因此可以根据需要对数据使用填充美学。编写此代码都是为了使用上面定义的值,而不是实际数字,因此,您无需更改下面的代码即可绘制不同区域的地图,只需更新上面定义的值即可。

#define a constant (scaled to map size) width for grid rectangles
#may need to adjust number to get width you prefer
grid.width <- (max.lat - min.lat)/90

is.even <- function(x) x %% 2 == 0 #function to test if number is even

#dataframe of longitude rectangles
rects.long <- data.frame(x_start = rep(seq(min.long, max.long - interval.long,
                                  by = interval.long), 2))
rects.long$x_end <- rects.long$x_start + interval.long
rects.long$y_start <- c(rep(min.lat, nrow(rects.long)/2),
                        rep(max.lat - grid.width, nrow(rects.long)/2))
rects.long$y_end <- c(rep(min.lat + grid.width, nrow(rects.long)/2),
                        rep(max.lat, nrow(rects.long)/2))

rects.long$color <- if(is.even(nrow(rects.long)/2)) { #even/odd test
  rep(c("black", "white"), nrow(rects.long)/2) #pattern for even
} else {
  rep(c(rep(c("black", "white"), (nrow(rects.long) - 2)/4),"black"), 2)} #odd

#dataframe of latitude rectangles
rects.lat <- data.frame(y_start = rep(seq(min.lat, max.lat - interval.lat,
                                           by = interval.lat), 2))
rects.lat$y_end <- rects.lat$y_start + interval.lat
rects.lat$x_start <- c(rep(min.long, nrow(rects.lat)/2),
                        rep(max.long - grid.width, nrow(rects.lat)/2))
rects.lat$x_end <- c(rep(min.long + grid.width, nrow(rects.lat)/2),
                      rep(max.long, nrow(rects.lat)/2))

rects.lat$color <- if(is.even(nrow(rects.lat)/2)) { #even/odd test
  rep(c("black", "white"), nrow(rects.lat)/2) #pattern for even
} else {
  rep(c(rep(c("black", "white"), (nrow(rects.lat) - 2)/4),"black"), 2)} #odd

#combine latitude and longitude grid
rects.grid <- rbind(rects.lat, rects.long)

#split into black dataframe and white dataframe
rects.black <- rects.grid[rects.grid$color == "black",]
rects.white <- rects.grid[rects.grid$color == "white",]

最后,让你的情节!

#define axis breaks to match grid
axis.breaks.x <- seq(min.long, max.long, interval.long)
axis.breaks.y <- seq(min.lat, max.lat, interval.lat)

ggplot(data = world) +
  geom_polygon(aes(x = long, y = lat, group = group),
               color = "black", fill = "gray50") +
  #set limits to your previously defined limits
  coord_fixed(1, xlim = c(min.long, max.long), ylim = c(min.lat, max.lat),
              expand = FALSE) +
  #define breaks same as grid, duplicate axes for lat/long labels on all sides
  scale_y_continuous(breaks = axis.breaks.y, sec.axis = dup_axis()) +
  scale_x_continuous(breaks = axis.breaks.x, sec.axis = dup_axis()) +
  #use geom_rect() to add border grid
  geom_rect(data = rects.white, inherit.aes = FALSE, #white grid rectangles
        aes(xmin = x_start, xmax = x_end, ymin = y_start, ymax = y_end), 
            color = "black", fill = "white") +
  geom_rect(data = rects.black, inherit.aes = FALSE, #black grid rectangles
        aes(xmin = x_start, xmax = x_end, ymin = y_start, ymax = y_end),
            color = "black", fill = "black") +
  theme_minimal() + #theme edits to make plot look like a map
  theme(axis.title = element_blank(),
        legend.position = "none")

enter image description here

这是一项测试,以检查此代码在不同的限制和间隔下是否有效:

min.lat <- -10
max.lat <- 50
interval.lat <- 10
min.long <- 60
max.long <- 150
interval.long <- 15
#run same code as above to create grid dataframes and plot

enter image description here