ggplot, sf package, Как сделать простой круговой график на карте - PullRequest
0 голосов
/ 07 июня 2019

Я хотел бы сделать круговую диаграмму с пакетом ggplot и sf. У меня есть очень простые данные, и я не думаю, что есть простой способ сделать. Все мои данные являются источниками:

data <- data.frame(Territory = c(1, 2, 3, 4, 5), 
                      Pins = c(25, 45, 45, 60, 75),
                      oak = c(45, 50, 45, 20, 15), 
                      land = c(30, 5, 10, 20, 10), 
                      sum = c(100, 100, 100, 100, 100))

И код моего графика:

read_sf("territories.shp") %>%
  left_join(data, by = "Territory") %>%
  ggplot() +
  geom_sf(aes(fill = Pins), color = "black") + theme_bw() +
  xlab("") + ylab("") +
  scale_fill_distiller(palette = "Spectral") +
  geom_sf_text(aes(label = Territory), colour = "coral4", size = 4) 

В моем шейп-файле у меня есть информация о n ° территории, поэтому мне не нужно было вводить информацию о долготе и широте. Когда я использовал geom_sf_text, метки помещались в центр каждой части карты, и именно здесь я хотел бы поставить свои пироги.

Вы знаете простой способ, чтобы помочь мне, пожалуйста?

спасибо!

1 Ответ

3 голосов
/ 08 июня 2019

Я не знаю, насколько этот код короче, чем ответы в ветке, которую вы связали, но он по крайней мере использует пакет sf. Вот одна альтернатива, использующая пакет cowplot. Я рассматривал круговые диаграммы следующим образом: https://www.r -spatial.org / r / 2018/10/25 / ggplot2-sf-3.html

library(sf)
library(tidyr)
library(dplyr)
library(ggplot2)
library(cowplot)


states        <- sf::st_as_sf(maps::map("state", plot = FALSE, fill = TRUE))
state_coords <- st_coordinates(st_centroid(states)) %>%
  data.frame(stringsAsFactors = FALSE) %>%
  mutate(ID = states$ID) %>%
  mutate(X = (abs(abs(X) - abs(st_bbox(states)$xmin)) /
      as.numeric(abs(st_bbox(states)$xmin) - abs(st_bbox(states)$xmax))) - 0.5,
        Y = abs(abs(abs(Y) - abs(st_bbox(states)$ymin)) /
         as.numeric(abs(st_bbox(states)$ymin) - abs(st_bbox(states)$ymax))
        ))

dt     <- data.frame(Territory = c(1, 2, 3, 4, 5),
                   ID = c("california", "wyoming", "new york",
                          "kansas", "georgia"),
                   pins = c(25, 45, 45, 60, 75),
                   oak = c(45, 50, 45, 20, 15),
                   land = c(30, 5, 10, 20, 10))
res <- tidyr::gather(dt, key = "key", value = "value", -Territory, -ID) %>%
  left_join(state_coords)

make_pie <- function(dt, title = NA, legend.position = 0){
  if(is.na(title)){
    title <- unique(dt$ID)
  }
  ggplot() +
    geom_bar(data = dt,
             aes(x = "", y = value, fill = key),
             stat = "identity", width = 1) +
    coord_polar("y") +
    theme_void() +
    theme(legend.position = legend.position) +
    ggtitle(title)
}

terr1 <- make_pie(dplyr::filter(res, Territory == 1))
terr2 <- make_pie(dplyr::filter(res, Territory == 2))
terr3 <- make_pie(dplyr::filter(res, Territory == 3))
terr4 <- make_pie(dplyr::filter(res, Territory == 4))
terr5 <- make_pie(dplyr::filter(res, Territory == 5))

(gg_states <- ggplot(data = states) +
  geom_sf() +
    scale_x_continuous(expand = c(0, 0)) +
    scale_y_continuous(expand = c(0, 0 )) +
  theme(legend.position = 0,
        plot.margin = unit(c(0,0,0,0), "cm"))
    )

leg <- get_legend(make_pie(res, "", legend.position = "left"))

draw_plot_loc <- function(plot, dt){
  draw_plot(plot, x = dt$X[1], y = dt$Y[1],
            height = 0.2)
}

(all <-
ggdraw(gg_states) +
  draw_plot_loc(terr1, dplyr::filter(res, Territory == 1)) +
  draw_plot_loc(terr2, dplyr::filter(res, Territory == 2)) +
  draw_plot_loc(terr3, dplyr::filter(res, Territory == 3)) +
  draw_plot_loc(terr4, dplyr::filter(res, Territory == 4)) +
  draw_plot_loc(terr5, dplyr::filter(res, Territory == 5))
  )

cowplot::plot_grid(all, leg, rel_widths = c(1, 0.1))

enter image description here

Я получил большую часть пути грубого форсирования вычислений между географическими координатами и сеткой draw_plot 0-1, но это не идеально.

...