在 ggplot2 中绘制岛屿
Plotting Islands in ggplot2
我试图在我的地图上绘制水体,并在 ggplot2 中与岛屿作斗争。我了解 exterior/interior 环的 right/left-hand 规则,但从一个岛到另一个岛仍然存在问题。问题是如何在 ggplot2 中绘制包含大量 holes/islands 的多边形?我相信诀窍在于顺序,但顺序是什么?
这是我为尝试理解和解决问题而构建的 MWE:
library(ggplot2)
ids <- letters[1]
# IDs and values to use for fill colour
values <- data.frame(
id = ids,
value = c(5)
)
# Example of good polygon and holes
good_positions <- data.frame(
id = rep(ids, each = 5),
# shape hole hole hole
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 5,6,6,5,5)
)
# Example of good polygon and holes
bad_positions <- data.frame(
id = rep(ids, each = 5),
# shape hole hole hole
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 3,4,4,3,3)
)
# Merge positions and values
good_datapoly <- merge(values, good_positions, by=c("id"))
bad_datapoly <- merge(values, bad_positions, by=c("id"))
# Plot polygons
good_plot <- ggplot(good_datapoly, aes(x=x, y=y)) +
geom_polygon(aes(group=id, fill=factor(value))) +
scale_fill_discrete("Key")
bad_plot <- ggplot(bad_datapoly, aes(x=x, y=y)) +
geom_polygon(aes(group=id, fill=factor(value))) +
scale_fill_discrete("Key")
good_plot
bad_plot
正如我在上面评论的那样,我不知道为什么我们会看到好例子和坏例子之间的差异。但是,这种 geom_holygon
的方法适用于不良位置数据。
library(proto)
library(ggplot2)
bad_positions <- data.frame(id = rep(ids, each = 5),
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 3,4,4,3,3)
)
### Assign unique ids to polygons
bad_positions$id <- rep(c(1,2,3,4), each = 5)
### geom_holygon
### http://rstudio-pubs-static.s3.amazonaws.com/3522_52420d28ca7d443eae79850822ead5b8.html
geom_holygon <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity",
rule = "winding", ...) {
GeomHolygon$new(mapping = mapping, data = data, stat = stat, position = position,
rule = rule, ...)
}
GeomHolygon <- proto(ggplot2:::GeomPolygon, {
objname <- "holygon"
draw <- function(., data, scales, coordinates, rule, ...) {
n <- nrow(data)
if (n == 1)
return()
munched <- coord_munch(coordinates, data, scales)
munched <- munched[order(munched$group), ]
first_idx <- !duplicated(munched$group)
first_rows <- munched[first_idx, ]
ggname(.$my_name(), gTree(children = gList(pathGrob(munched$x, munched$y,
default.units = "native", id = munched$group, rule = rule, gp = gpar(col = first_rows$colour,
fill = alpha(first_rows$fill, first_rows$alpha), lwd = first_rows$size *
.pt, lty = first_rows$linetype)))))
}
})
### Draw the figure
ggplot() +
geom_holygon(bad_positions, mapping = aes(x = x, y = y, group = id), fill = "skyblue")
我试图在我的地图上绘制水体,并在 ggplot2 中与岛屿作斗争。我了解 exterior/interior 环的 right/left-hand 规则,但从一个岛到另一个岛仍然存在问题。问题是如何在 ggplot2 中绘制包含大量 holes/islands 的多边形?我相信诀窍在于顺序,但顺序是什么?
这是我为尝试理解和解决问题而构建的 MWE:
library(ggplot2)
ids <- letters[1]
# IDs and values to use for fill colour
values <- data.frame(
id = ids,
value = c(5)
)
# Example of good polygon and holes
good_positions <- data.frame(
id = rep(ids, each = 5),
# shape hole hole hole
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 5,6,6,5,5)
)
# Example of good polygon and holes
bad_positions <- data.frame(
id = rep(ids, each = 5),
# shape hole hole hole
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 3,4,4,3,3)
)
# Merge positions and values
good_datapoly <- merge(values, good_positions, by=c("id"))
bad_datapoly <- merge(values, bad_positions, by=c("id"))
# Plot polygons
good_plot <- ggplot(good_datapoly, aes(x=x, y=y)) +
geom_polygon(aes(group=id, fill=factor(value))) +
scale_fill_discrete("Key")
bad_plot <- ggplot(bad_datapoly, aes(x=x, y=y)) +
geom_polygon(aes(group=id, fill=factor(value))) +
scale_fill_discrete("Key")
good_plot
bad_plot
正如我在上面评论的那样,我不知道为什么我们会看到好例子和坏例子之间的差异。但是,这种 geom_holygon
的方法适用于不良位置数据。
library(proto)
library(ggplot2)
bad_positions <- data.frame(id = rep(ids, each = 5),
x = c(1,10,10,1,1, 2,2,3,3,2, 7,7,8,8,7, 5,5,6,6,5 ),
y = c(1,1,10,10,1, 2,3,3,2,2, 7,8,8,7,7, 3,4,4,3,3)
)
### Assign unique ids to polygons
bad_positions$id <- rep(c(1,2,3,4), each = 5)
### geom_holygon
### http://rstudio-pubs-static.s3.amazonaws.com/3522_52420d28ca7d443eae79850822ead5b8.html
geom_holygon <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity",
rule = "winding", ...) {
GeomHolygon$new(mapping = mapping, data = data, stat = stat, position = position,
rule = rule, ...)
}
GeomHolygon <- proto(ggplot2:::GeomPolygon, {
objname <- "holygon"
draw <- function(., data, scales, coordinates, rule, ...) {
n <- nrow(data)
if (n == 1)
return()
munched <- coord_munch(coordinates, data, scales)
munched <- munched[order(munched$group), ]
first_idx <- !duplicated(munched$group)
first_rows <- munched[first_idx, ]
ggname(.$my_name(), gTree(children = gList(pathGrob(munched$x, munched$y,
default.units = "native", id = munched$group, rule = rule, gp = gpar(col = first_rows$colour,
fill = alpha(first_rows$fill, first_rows$alpha), lwd = first_rows$size *
.pt, lty = first_rows$linetype)))))
}
})
### Draw the figure
ggplot() +
geom_holygon(bad_positions, mapping = aes(x = x, y = y, group = id), fill = "skyblue")