Я использовал этот нить для построения пространственной тепловой карты. Разница в том, что я не хочу вычислять плотность точек, потому что у меня уже есть значение уровня «нагрева». Подробно я хочу построить график плотности населения кантона Берн (Швейцария) с цветовыми градиентами.
Данные о населении получены от швейцарского статистического управления и подсчитывают количество жителей на гектар (площадь 100 м x 100 м), загружаемый здесь (файл «STATPOP2020.csv»). Основываясь на ответе jlhoward в нить, мой код пока таков:
library(tidyverse)
library(rgdal)
library(GADMTools)
library(RColorBrewer)
# conversion from swiss coordinate system to wgs-84
lv03_wgs_lat <- function (y, x){
y_aux <- (y - 600000)/1000000
x_aux <- (x - 200000)/1000000
lat <- {16.9023892 +
3.238272 * x_aux -
0.270978 * (y_aux^2) -
0.002528 * (x_aux^2) -
0.0447 * (y_aux^2) * x_aux -
0.0140 * (x_aux^3)}
lat <- lat * 100/36
return(lat)
}
lv03_wgs_lon <- function (y, x){
y_aux <- (y - 600000)/1000000
x_aux <- (x - 200000)/1000000
lon <- {2.6779094 +
4.728982 * y_aux +
0.791484 * y_aux * x_aux +
0.1306 * y_aux * (x_aux^2) -
0.0436 * (y_aux^3)}
lon <- lon * 100/36
return(lon)
}
# read in data
d_pop <- read_csv2("STATPOP2020.csv") %>%
select(1:6) %>%
rename(TOT = 6) %>%
mutate(lon = lv03_wgs_lon(X_KOORD, Y_KOORD),
lat = lv03_wgs_lat(X_KOORD, Y_KOORD))
# filter swiss data to canton of berne
d_map_ch <- gadm_sf.loadCountries("CHE", level = 1)
d_map_be <- gadm_subset(d_map_ch, level = 1, regions = "Bern", usevar = NULL)
d_map_points <- st_as_sf(d_pop, coords = c("lon", "lat"), crs = 4326)
d_pop_be <- bind_cols(d_pop,
as_tibble(t(st_contains(x = d_map_be$sf, y = d_map_points, sparse = FALSE))) %>%
rename(in_be = V1)) %>%
filter(in_be)
# building on previous answer, administrative border is disregarded
ggplot(d_pop_be, aes(x = E_KOORD, y = N_KOORD)) +
stat_density2d(aes(fill = TOT), alpha = 0.4, geom = "polygon")+
scale_fill_gradientn(colours=rev(brewer.pal(7,"Spectral")))+
xlim(2555000, 2678000) +
ylim(1130000, 1245000) +
coord_fixed()
По мере построения тепловой карты я не получаю легенду для «тепла», плотности населения и не могу добавлять цвета к градиентам. Кто-нибудь знает, как их добавить?
Я ценю вашу помощь!
Проблема, как вы уже установили, заключается в том, что вам нужна контурная карта, которая представляет плотность населения, а не плотность измерения, что и делает stat_density_2d
. Создать такой объект в R можно является, но это сложно, когда измерения не распределены по сетке регулярно (как в случае с этими данными). По этой причине лучше всего использовать geom_point
здесь:
ggplot(d_pop_be, aes(x = E_KOORD, y = N_KOORD)) +
geom_point(aes(color = log(TOT), alpha = exp(TOT))) +
scale_colour_gradientn(colours=rev(brewer.pal(7,"Spectral")),
breaks = log(c(1, 10, 100, 1000)),
labels = c(1, 10, 100, 1000),
name = "Population density\n(People per hectare)")+
xlim(2555000, 2678000) +
ylim(1130000, 1245000) +
guides(alpha = guide_none()) +
coord_fixed()
Если вам нужен заполненный контур, вам придется вручную создать матрицу, охватывающую интересующую область, получить среднее значение населения в каждом бине, преобразовать его во фрейм данных, а затем использовать geom_contour_filled
:
z <- tapply(d_pop_be$TOT, list(cut(d_pop_be$E_KOORD, 200),
cut(d_pop_be$N_KOORD, 200)), mean, na.rm = TRUE)
df <- expand.grid(x = seq(min(d_pop_be$E_KOORD), max(d_pop_be$E_KOORD), length = 200),
y = seq(min(d_pop_be$N_KOORD), max(d_pop_be$N_KOORD), length = 200))
df$z <- c(tapply(d_pop_be$TOT, list(cut(d_pop_be$E_KOORD, 200),
cut(d_pop_be$N_KOORD, 200)), mean, na.rm = TRUE))
df$z[is.na(df$z)] <- 0
ggplot(df, aes(x, y)) +
geom_contour_filled(aes(z = z), breaks = c(1, 5, 20, 50, 100, 1000)) +
scale_fill_manual(values = rev(brewer.pal(5, "Spectral")))
@Oubi для полноты картины я показал, как можно использовать заполненный контур. Получить данные в правильном формате сложнее, но, вероятно, это немного понятнее, чем geom_point
Мне немного больше нравится подход с geom_countour_filled, так как вы не можете видеть точки. Спасибо за вашу помощь!
Вместо этого я изменил свою стратегию и сюжетные точки, как вы рекомендовали. Гораздо проще, и данные визуализируются более интуитивно понятным способом. Спасибо за вашу помощь, я ценю это.