在 R 中制作 WCS Munsell 颜色图表,scale_fill_manual、ggplot2 中的顺序问题

Ann*_*rie 2 r colors ggplot2

我想为世界色彩调查所使用的芯片制作孟塞尔色彩图表。它应该看起来像这样:

在此输入图像描述

需要的信息可以在WCS页面上找到,这里,我采取以下步骤:

library(munsell) # https://cran.r-project.org/web/packages/munsell/munsell.pdf
library(ggplot2)

# take the "cnum-vhcm-lab-new.txt" file from: https://www1.icsi.berkeley.edu/wcs/data.html#wmt
# change by replacing .50 with .5 removing .00 after hue values

WCS <- read.csv("cnum-vhcm-lab-new.txt", sep = "\t", header = T)
WCS$hex <- mnsl2hex(hvc2mnsl(hue = WCS$MunH, value = ceiling(WCS$MunV), chroma = WCS$C), fix = T)

# this works, but the order of tiles is messed up
ggplot(aes(x=H, y=V, fill=hex), data = WCS) +   
  geom_tile(aes(x=H, y=V), show.legend = F) +
  scale_fill_manual(values = WCS$hex) +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 40)) 
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

显然,这些碎片不是按照色调和明度排序的,而是参考一些其他维度,甚至可能是原始数据帧中的顺序。我还必须恢复 y 轴上的顺序。factor()我想解决方案将与和相关reorder(),但如何做到呢?

che*_*123 5

OP。TL;DR - 你应该使用scale_fill_identity()而不是scale_fill_manual().

现在进行详细描述:其核心是将数据列映射ggplot2到绘图上的特定特征的函数,这指的是使用该函数的“美学”。定位是通过将数据的某些列映射到美学来定义的,并且图块中的不同颜色也映射到使用。ggplot2aes()xyfillaes()

的映射fill不指定颜色,而仅指定哪些东西应该是不同的颜色。当以这种方式映射时,这意味着数据(观察)中在映射到美学的列中具有相同值的fill行将具有相同的颜色,而在映射到美学的列中具有不同值的观察fill将具有不同的颜色。重要的是,这不指定颜色,而仅指定颜色是否应该不同!

默认行为是ggplot2通过应用默认比例来确定要使用的颜色。对于连续(数字)值,应用连续比例,对于离散值(如字符向量),应用离散比例。

要查看默认行为,只需scale_fill_manual(...)从绘图代码中删除即可。我在下面重新复制了您的代码,并添加了所需的修订,以编程方式删除".50"".00"调整WCS$MunH. 如果您从提供的链接下载了原始 .txt 文件,下面的代码应该完全有效。

library(munsell)
library(ggplot2)

WCS <- read.csv("cnum-vhcm-lab-new.txt", sep = "\t", header = T)
WCS$MunH <- gsub('.50','.5', WCS$MunH)  # remove trailing "0" after ".50"
WCS$MunH <- gsub('.00',  '', WCS$MunH)  # remove ".00" altogether

WCS$V <- factor(WCS$V)  # needed to flip the axis

WCS$hex <- mnsl2hex(hvc2mnsl(hue = WCS$MunH, value = ceiling(WCS$MunV), chroma = WCS$C), fix = T)

ggplot(aes(x=H, y=V, fill=hex), data = WCS) +   
  geom_tile(aes(x=H, y=V), show.legend = F, width=0.8, height=0.8) +
  scale_y_discrete(limits = rev(levels(WCS$V))) +  # flipping the axis
  scale_x_continuous(breaks = scales::pretty_breaks(n = 40)) +
  coord_fixed() + # force all tiles to be "square"
  theme(
    panel.grid = element_blank()
  )
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

show.legend = F在那里,但应该有 324 个不同的值映射到WCS$hex列(即length(unique(WCS$hex)))。

使用时scale_fill_manual(values=...),您提供要使用的颜色的名称,但它们不会映射到列中的相同位置WCS$hex。它们根据ggplot2决定组织级别的方式来应用WCS$hex,就好像它是一个因素一样。

为了告诉ggplot2您基本上忽略映射并仅根据您在映射到的列中看到的实际颜色名称进行颜色fill,您可以使用scale_fill_identity(). 这必然会删除显示任何图例的能力,因为它有点删除了默认行为的映射和重新着色aes(fill=...)。无论如何,这应该可以解决您的问题:

ggplot(aes(x=H, y=V, fill=hex), data = WCS) +   
  geom_tile(aes(x=H, y=V), width=0.8, height=0.8) +
  scale_fill_identity() +   # assign color based on text
  scale_y_discrete(limits = rev(levels(WCS$V))) +  # flipping the axis
  scale_x_continuous(breaks = scales::pretty_breaks(n = 40)) +
  coord_fixed() + # force all tiles to be "square"
  theme(
    panel.grid = element_blank()
  )
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述