【问题标题】:Making a specific legend in R ggplot: manually assigning colors and values polygons should take在 R ggplot 中制作特定图例:手动分配颜色和值多边形应该采用
【发布时间】:2017-02-10 17:44:43
【问题描述】:

我目前正在尝试制作一张地图,它 1) 用各自的名称标记每个多边形,以及 2) 根据每个多边形的计数数量为每个多边形赋予特定的颜色。

阅读了几篇 Stack Overflow 帖子,我发现了一篇对我有很大帮助的帖子 (Labeling center of map polygons in R ggplot),但我遇到了两个主要问题:1) 我似乎无法指定我希望地图采用的具体颜色, 和 2) 我似乎无法按照我想要的方式获得传说。

我将使用我之前提到的帖子 (Labeling center of map polygons in R ggplot) 中用户 Silverfish 提供的代码:

library(rgdal) # used to read world map data
library(rgeos) # to fortify without needing gpclib
library(maptools)
library(ggplot2)
library(scales) # for formatting ggplot scales with commas

#Data from http://thematicmapping.org/downloads/world_borders.php.
#Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
#Unpack and put the files in a dir 'data'

worldMap <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
# Change "data" to your path in the above!
worldMap.fort <- fortify(worldMap, region = "ISO3")
# Fortifying a map makes the data frame ggplot uses to draw the map outlines.
# "region" or "id" identifies those polygons, and links them to your data. 
# Look at head(worldMap@data) to see other choices for id.
# Your data frame needs a column with matching ids to set as the map_id aesthetic in ggplot. 
idList <- worldMap@data$ISO3
# "coordinates" extracts centroids of the polygons, in the order listed at worldMap@data
centroids.df <- as.data.frame(coordinates(worldMap))
names(centroids.df) <- c("Longitude", "Latitude")  #more sensible column names
# This shapefile contained population data, let's plot it.
popList <- worldMap@data$POP2005

pop.df <- data.frame(id = idList, population = popList, centroids.df)

ggplot(pop.df, aes(map_id = id)) + #"id" is col in your df, not in the map object 
  geom_map(aes(fill = population), colour= "grey", map = worldMap.fort) +
  expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
  scale_fill_gradient(high = "red", low = "white", guide = "colorbar", labels = comma) +
  geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
  coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
  labs(x = "Longitude", y = "Latitude", title = "World Population") +
  theme_bw() 

This is what the code currently outputs

这个示例让我学习了如何在地图中的多边形上放置标签,但我需要做一些更改才能到达我需要的位置: 1)我需要比例不是渐变,而是以图例的形式为特定范围的值提供颜色。我想要的颜色和范围如下(颜色以 HEX 形式指定): - 范围:0 颜色:“白色” - 范围:1-99 颜色:“#d3c874” - 范围:100-249 颜色:“#d69b26” - 范围:250-499 颜色:“#89280d” - 范围:500+ 颜色:“#411614”

2)我需要图例出现在底部并从左到右

3) 我需要多边形根据它们的计数来获取正确的颜色

在“pop.df”数据框中,我创建了另一列(类别),根据我之前提到的范围分配值“1”、“2”、“3”、“4”或“5” : - 范围:0 值:“1” - 范围:1-99 值:“2” - 范围:100-249 值:“3” - 范围:250-499 值:“4” - 范围:500+ 值:“5” (注意:看到此示例中使用的计数非常大,我知道每个多边形很可能超过 500+,这些只是我使用的范围)。

我这样做是为了在绘制地图时更容易为多边形分配颜色。基本上,我认为这种方式比创建首先检查计数、将其与范围进行比较然后给出颜色的代码更容易。我会澄清它不需要这样做,我只是说我已经接近它的方式。

我使用这段代码来实现这一点:

Pop.df$Categ <- ifelse(Pop.df$population < 1, "1",
                             ifelse(Pop.df$population >= 1 & Pop.df$population < 100, "2", 
                                    ifelse(Pop.df$population >= 100 & Pop.df$population < 250, "3", 
                                           ifelse(Pop.df$population >= 250 & Pop.df$population < 500, "4", "5"))))

看到我需要的颜色不是特定调色板的一部分,并且我需要地图中的那些特定颜色,我开始使用“scale_colour_manual”而不是“scale_fill_gradient”方法来调整我需要的图例,但它似乎没有工作。我面临的具体障碍是: a)我似乎无法使图例从渐变到离散值 b) 地图中的一些颜色与我需要的颜色完全不同。不知道是不是HEX码的原因还是别的原因。

我已经通过多种方式解决了这个问题。我最近使用的代码是这个:

ggplot(pop.df, aes(map_id = id)) +
geom_map(aes(fill = population), colour= "black", map
= worldMap.fort) +
expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) + 
scale_colour_manual(values = c("white", "#d3c874", "#d69b26", "#89280d", "#411614"), 
                      limits = c("1", "2", "3", "4", "5"), breaks = c("1", "2", "3", "4", "5")) + #This is my attempts to getting the legend to work
geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
labs(x = "Longitude", y = "Latitude", title = "World Population") +
theme_bw()

关于图例的位置,我什至还没有开始解决这个问题,因为我首先尝试让它正确显示。

任何见解都会令人惊叹!谢谢

【问题讨论】:

    标签: r ggplot2 colors legend


    【解决方案1】:

    最终,您需要为 fill 美学提供离散的类别变量,而不是连续的总体变量。然后使用scale_fill_manual(),因为您想用颜色填充国家(而不是为其边界着色),并且您已经在geom_map() 中将边界着色为黑色。请参阅下面的带有 cmets 的代码。

    # same code as in your question, 
    # but (1) changed population categories (added four zeroes) so that
    # more countries fall in different bins, 
    # (just so I could see if my subsequent solutions worked)
    # and (2) used the hex colors you supplied as category values, rather than 1-5
    pop.df$Categ <- ifelse(pop.df$population < 1, "#ffffff",
                       ifelse(pop.df$population >= 1 & pop.df$population < 1000000, "#d3c874", 
                              ifelse(pop.df$population >= 1000000 & pop.df$population < 2500000, "#d69b26", 
                                     ifelse(pop.df$population >= 2500000 & pop.df$population < 5000000, "#89280d", "#411614"))))
    # convert Categ to factor
    pop.df$Categ <- factor(pop.df$Categ, levels = c("#ffffff", "#d3c874", "#d69b26", "#89280d", "#411614"))
    # plot
    ggplot(pop.df, aes(map_id = id)) +
      geom_map(aes(fill=Categ), colour= "black", map = worldMap.fort) +
      expand_limits(x = worldMap.fort$long, y = worldMap.fort$lat) +
      scale_fill_manual(values = c("#ffffff", "#d3c874", "#d69b26", "#89280d", "#411614"), 
                  breaks = c("#ffffff", "#d3c874", "#d69b26", "#89280d", "#411614"), 
                  labels = c("zero", "< 1 million", "1 to 2.5 million", "2.5 to 5 million", "> 5 million")) 
      geom_text(aes(label = id, x = Longitude, y = Latitude)) + #add labels at centroids
      coord_equal(xlim = c(-90,-30), ylim = c(-60, 20)) + #let's view South America
      labs(x = "Longitude", y = "Latitude", title = "World Population") +
      theme_bw()
    

    (我知道您有理由指定您的人口类别。我只是更改了它们,以便更容易地了解我所做的事情是否有效。)

    该代码应返回以下图:

    然后您可以通过添加+ theme(legend.position = ...) 来更改图例的位置,其中可接受的值为“top”、“bottom”、“left”、“right”、“none”或从零到一坐标系(例如,c(0.5, 0.5) 会将您的图例放在图的中间)。

    因此,将+ theme(legend.position = c(0.83, 0.857), legend.background = element_rect(fill="transparent",colour=NA)) 添加到您的 ggplot 对象会产生:

    【讨论】:

    • 代码完美运行,非常感谢!我想看看我是否可以问一些后续问题以理解代码而不是真正使用我不理解的东西:1)在scale_fill_manual:说breaks和@987654334是否正确@ 一起确定每个多边形的颜色是什么? 2) 如果是这样,那么在scale_fill_manual 上下文中使用的limits 选项是什么?
    • breaks 指定您的类别值的顺序出现在图例中,但 limits 指定哪些类别值得到哪些颜色(尽管我个人从未遇到过值顺序的情况需要不同于图例中显示的顺序)。因此,如果您指定了limits=c("3","1","2","4","5"),那么类别值“3”将获得values 下指定的第一个颜色。请参阅docs.ggplot2.org/0.9.3/scale_manual.html 的最后三个示例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 2019-10-22
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    相关资源
    最近更新 更多