简体   繁体   English

用国家/地区的值作为 R 中的颜色绘制地图?

[英]Plot map with values for countries as color in R?

I have following simple example data which I want to plot on a map with gradient color corresponding to value of the given country.我有以下简单的示例数据,我想用与给定国家/地区的值对应的渐变颜色在地图上绘制这些数据。

ddf = read.table(text="
country value
USA 10
UK 30
Sweden 50
Japan 70
China 90
Germany 100
France 80
Italy 60
Nepal 40
Nigeria 20
", header=T)

On google search, I found several sites.在谷歌搜索上,我找到了几个网站。 However, I am looking for code which is small and clear, and should preferably be fast (I found ggplot methods to be relativley slow).但是,我正在寻找小而清晰的代码,并且最好应该是快速的(我发现 ggplot 方法相对较慢)。 The resolution of world map need not be high.世界地图的分辨率不需要很高。

I tried following code:我尝试了以下代码:

library(maptools)
data(wrld_simpl)
plot(wrld_simpl)

Specific nations can be colored as given on : Using [R] maps package - colouring in specific nations on a world map Using the command:特定国家可以按照以下方式着色: 使用 [R] 地图包 - 在世界地图上的特定国家中着色使用命令:

plot(wrld_simpl, col = c(gray(.80), "red")[grepl("^U", wrld_simpl@data$NAME) + 1])

But how can I get map with above data in a gradient of colors.但是我怎样才能得到带有渐变颜色的上述数据的地图。 Thanks for your help.谢谢你的帮助。

Define "slow". 定义“慢”。 ggplot provides one of the most flexible ways to present data on maps at the the cost of a few extra seconds. ggplot提供了一种最灵活的方式,可以在几秒钟的时间内在地图上显示数据。

library(RColorBrewer)
library(maptools)
library(ggplot2)

data(wrld_simpl)

ddf = read.table(text="
                 country value
                 'United States' 10
                 'United Kingdom' 30
                 'Sweden' 50
                 'Japan' 70
                 'China' 90
                 'Germany' 100
                 'France' 80
                 'Italy' 60
                 'Nepal' 40
                 'Nigeria' 20", header=TRUE)

# Pascal had a #spiffy solution that is generally faster

plotPascal <- function() {

  pal <- colorRampPalette(brewer.pal(9, 'Reds'))(length(ddf$value))
  pal <- pal[with(ddf, findInterval(value, sort(unique(value))))]

  col <- rep(grey(0.8), length(wrld_simpl@data$NAME))
  col[match(ddf$country, wrld_simpl@data$NAME)] <- pal

  plot(wrld_simpl, col = col)

}

plotme <- function() {

  # align colors to countries

  ddf$brk <- cut(ddf$value, 
                 breaks=c(0, sort(ddf$value)), 
                 labels=as.character(ddf[order(ddf$value),]$country),
                 include.lowest=TRUE)

  # this lets us use the contry name vs 3-letter ISO
  wrld_simpl@data$id <- wrld_simpl@data$NAME

  wrld <- fortify(wrld_simpl, region="id")
  wrld <- subset(wrld, id != "Antarctica") # we don't rly need Antarctica

  gg <- ggplot()

  # setup base map
  gg <- gg + geom_map(data=wrld, map=wrld, aes(map_id=id, x=long, y=lat), fill="white", color="#7f7f7f", size=0.25)

  # add our colored regions
  gg <- gg + geom_map(data=ddf, map=wrld, aes(map_id=country, fill=brk),  color="white", size=0.25)

  # this sets the scale and, hence, the legend
  gg <- gg + scale_fill_manual(values=colorRampPalette(brewer.pal(9, 'Reds'))(length(ddf$value)), 
                               name="Country")

  # this gives us proper coords. mercator proj is default
  gg <- gg + coord_map()
  gg <- gg + labs(x="", y="")
  gg <- gg + theme(plot.background = element_rect(fill = "transparent", colour = NA),
                   panel.border = element_blank(),
                   panel.background = element_rect(fill = "transparent", colour = NA),
                   panel.grid = element_blank(),
                   axis.text = element_blank(),
                   axis.ticks = element_blank(),
                   legend.position = "right")
  gg

}

system.time(plotme())
##  user  system elapsed 
## 1.911   0.005   1.915 

system.time(plotthem())
##  user  system elapsed 
## 1.125   0.014   1.138 

The ggplot code produces the following map: ggplot代码生成以下映射:

在此输入图像描述

The timings vary per-run, but I've not seen them go more than a full minute apart (it appeard to average 0.6m on my system, but I wasn't about to do extensive benchmarking). 每次运行的时间有所不同,但我没有看到它们相隔超过一分钟(我的系统平均接近0.6米,但我不打算进行大量的基准测试)。

UPDATE UPDATE

As your requirements continue to be teased out, you can replace the discrete scale with a continuous one rather easily. 随着您的要求不断被淘汰,您可以相当容易地用连续的刻度替换离散刻度。

pal <- colorRampPalette(brewer.pal(9, 'Reds'))(length(ddf$value))
palSz <- 10 # not sure what you really want/need for this range

gg <- gg + scale_fill_gradient2(low = pal[1],
                                mid = pal[palSz/2],
                                high = pal[palSz],
                                midpoint = (max(ddf$value) + min(ddf$value)) / 2,
                                name="value")

在此输入图像描述

But, it sounds like you should probably stick with @Andy's rworldmap since it abstracts the complexity. 但是,听起来你可能应该坚持rworldmaprworldmap因为它抽象了复杂性。

You could use rworldmap if you wanted less code and a coarser resolution map. 如果你想要更少的代码和更粗糙的分辨率图,你可以使用rworldmap。

library(rworldmap)

#create a map-shaped window
mapDevice('x11')
#join to a coarse resolution map
spdf <- joinCountryData2Map(ddf, joinCode="NAME", nameJoinColumn="country")

mapCountryData(spdf, nameColumnToPlot="value", catMethod="fixedWidth")

Default categorisation, colours and legends can be altered, see this RJournal paper . 可以更改默认分类,颜色和图例,请参阅此RJournal报告

It would be faster with country codes rather than names. 国家代码而不是名称会更快。

rworldmap地图

Probably not optimized: 可能没有优化:

library(RColorBrewer)
library(maptools)
data(wrld_simpl)

ddf = read.table(text="
country value
'United States' 10
'United Kingdom' 30
'Sweden' 50
'Japan' 70
'China' 90
'Germany' 100
'France' 80
'Italy' 60
'Nepal' 40
'Nigeria' 20", header=TRUE)

Reds is the name of a color palette. Reds是调色板的名称。 See ?brewer.pal for other available palettes. 有关其他可用的调色板,请参阅?brewer.pal

pal <- colorRampPalette(brewer.pal(9, 'Reds'))(length(ddf$value))
pal <- pal[with(ddf, findInterval(value, sort(unique(value))))]

col <- rep(grey(0.8), length(wrld_simpl@data$NAME))
col[match(ddf$country, wrld_simpl@data$NAME)] <- pal

plot(wrld_simpl, col = col)

在此输入图像描述

I thought the other answers were slightly complicated, perhaps because this was asked/answered a relatively long time ago?我认为其他答案有点复杂,也许是因为这是在相对很久以前被问到/回答的? Here's a simple way using ggplot2 .这是使用ggplot2的简单方法。 I don't know what the benchmark is with respect to whether or not this is "fast".我不知道关于这是否“快速”的基准是什么。

library(ggplot2)
library(dplyr)

ddf = read.table(text="
country value
USA 10
UK 30
Sweden 50
Japan 70
China 90
Germany 100
France 80
Italy 60
Nepal 40
Nigeria 20
", header=T)

world <- map_data("world")

world %>%
  merge(ddf, by.x = "region", by.y = "country", all.x = T) %>%
  arrange(group, order) %>%
  ggplot(aes(x = long, y = lat, group = group, fill = value)) + geom_polygon()

世界地图,按值着色

This makes it easy to modify using all the common ggplot2 handles.这使得使用所有常见的ggplot2句柄进行修改变得容易。 For example, if we wanted to pretty this up quickly:例如,如果我们想快速优化一下:

library(viridis)

world %>%
  merge(ddf, by.x = "region", by.y = "country", all.x = T) %>%
  arrange(group, order) %>%
  ggplot(aes(x = long, y = lat, group = group, fill = value)) +
  geom_polygon(color = "white", size = 0.2) +
  scale_fill_viridis("", na.value = "gray90") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        panel.grid = element_blank())

更漂亮的地图,带有 viridis 色标,没有轴标题等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM