购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第二节
颜色

本节将介绍如何在R中表示颜色、在不同表示法之间进行转换以及根据需要生成颜色。

## 用showcolor函数方便地展示颜色

# install.packages("plothelper")

library(plothelper)

showcolor(c("red", "purple", "blue"))

一、颜色的表示

在R中,一些颜色拥有确切的名字,如"red"、"orangered"、"skyblue"等。

all_color=colors() # 用colors函数获取所有颜色名称,读者可查看课件中的"R语言颜色表.pdf"

set.seed(12345); showcolor(sample(all_color, 10), label_size=8)

没有名字的颜色,需使用RGB系统、十六进制法、HSB/HSV系统和HCL系统来表示。HSL系统和CMYK系统也是常用的颜色系统,但我们在此不作介绍。

1. RGB系统

## rgb函数用来把代表红色、绿色和蓝色的R、G、B三个值组合成一个颜色值;但注意,参数max Color Value的默认值是1而不是255

# 例如,要把红=23,绿=100,蓝=200转化成十六进制,有两种方法

rgb(red=23, green=100, blue=200, max Color Value=255) # "#1764C8"

rgb(red=23/255, green=100/255, blue=200/255) # "#1764C8"

# 转化结果是一个以#号打头的十六进制字符,这实际上是下边要讲到的十六进制颜色

x=rgb(c(255, 0, 30), c(10, 230, 0), c(20, 40, 66), max Color Value= 255) # 同时转化[255, 10, 20]、[0, 230, 40]、[30, 0, 66]这三个颜色

showcolor(x)

2. 十六进制

在十六进制表示法中,#号后有6个数字,第1和2位、第3和4位、第5和6位分别代表RGB系统中的三个值。

# 例如,红色的RGB值为255、0、0

x=as.hexmode(c(255, 0, 0)) # "ff" "00" "00"

x=as.character(x)

x=paste(c("#", x), collapse="") # "#ff0000"

# 注意:(1)字符前务必要加井号;(2)不用区分大小写

3. HSB/HSV系统

## 用hsv函数将HSB/HSV值转化成十六进制颜色

hsv(h=0.1667, s=1, v=1) # 代表色相、饱和度和明度的三个参数的取值范围为0至1;s和v的默认值都是1

x=hsv(h=c(0, 0.333, 0.666), v=0.6) # 同时生成红、绿、蓝三个颜色,并将明度设为0.6

showcolor(x)

4. HCL系统

HCL系统(亦被称为使用极坐标的CIELUV系统)是一种较为符合视觉感知的颜色系统,它通过色相(H)、色度(C)和亮度(L)来确定颜色。其中, H的取值范围是0至360,L的取值范围是0至100,而C的取值范围并非固定值,要根据H和L的值确定。下文关于表示法转换的部分,将会介绍生成HCL颜色的方法。

5. 透明度

透明度(alpha)的取值为0至1。较小的数值意味着图形背后的颜色会透出来,较大的数值意味着图形能够遮挡背后的颜色。

# install.packages("scales") # 手动设置透明度,需使用scales包

library(scales)

alpha("red", 0.3)

# 十六进制的颜色字符有八位,其最后两位表示透明度;当颜色的透明度变化时,它的前六位不变

mycolor=alpha("red", c(0.3, 0.5, 1)) # 同时生成有不同透明度的三个红色

showcolor(mycolor)

hsv(h=0.1667, s=1, v=1, alpha=0.5) # 在hsv函数中用alpha参数指定alpha值

rgb(23/255, 100/255, 200/255, alpha=0.5) # 在rgb函数中,由于alpha的取值范围是0至1,所以为防止出现错误,请把前三个值的取值范围也改为0至1

二、颜色表示法之间的转换

在可视化过程中,我们会遇到不同的颜色表示法。那么,如何把一种表示法转化成另一种表示法呢?实际上,上文已经提到了如何把RGB、HSB/HSV表示法转化成十六进制表示法,而接下来我们将主要学习由farver包提供的转化方法。farver包为不同表示法之间的转换提供了方便且统一的界面。至于R自带的col2rgb、rgb2hsv等转化函数,读者如有需要可自行学习。

library(farver)

## decode_colour可将颜色名或十六进制表示法转化成其他表示法。其中, colour为颜色向量。alpha用于设置是否输出透明度(对于像"red"这样的无透明度信息的颜色,函数会将透明度设为1)。to用于设置我们希望使用的表示法,选项包括我们在上文中提到的"rgb"、"hsv"、'hcl"以及在某些情况下会用到的"cmyk"、"hsl"等

x=c("red", "#0000ff", "#00ff00cc", NA) # 缺失值将不会被转化

decode_colour(x, alpha=TRUE, to="rgb")

# 当to="rgb"时,矩阵的前3列显示值域为0至255的RGB值。由于alpha= TRUE,所以第4列用于显示透明度

# r g b alpha

# [1,] 255 0 0 1.0

# [2,] 0 0 255 1.0

# [3,] 0 255 0 0.8

# [4,] NA NA NA NA

decode_colour(colour=x, alpha=FALSE, to="hsv") # 转为HSV。注意:此处H的值域不是0至1,而是0至360

decode_colour(colour=x, alpha=FALSE, to="hcl") # 转为HCL

## encode_colour用于实现decode_colour的逆操作,即把其他表示法转回十六进制表示法。其中,colour为数值矩阵,它的每一行代表一个颜色。矩阵的列数应根据需要确定,例如,若from="rgb" (即初始值为RGB值),则矩阵应包含分别代表R、G、B的三列。alpha为透明度向量,当它为NULL时,结果不包含透明度。from的选项与decode_colour的to参数相同

x=matrix(c(255, 0, 0, 0, 0, 255), nrow=2)

encode_colour(colour=x, alpha=c(1, 0.5), from="rgb")

encode_colour(colour=matrix(c(120, 1, 1), nrow=1), from="hsv") # 注意:即使待转换的颜色只有一个,数值也必须用矩阵给出

## convert_colour用于实现多种表示法之间的转换。其中,from和to分别表示初始表示法和转化后的表示法

x=matrix(c(255, 0, 0, 0, 0, 255), nrow=2) # 将红色和蓝色的RGB值转为HCL值

res1=convert_colour(colour=x, from="rgb", to="hcl")

res2=convert_colour(colour=res1, from="hcl", to="rgb") # 四舍五入后与x相同

## get_channel和set_channel用于实现在不对十六进制表示法进行转化的情况下获取、更改颜色通道的操作。其中,colour为颜色向量。channel和space用于设置待获取或修改的通道和这个通道所在的空间。例如,对RGB表示法而言,R (红色)通道"r"和透明度通道"alpha"是可以被修改的;而对于HSV表示法而言,"r"通道是无法修改的,因为这个通道不存在。value用于设置修改后的数值

x=c("red", "purple", "#0000ff", "#00ff00cc")

get_channel(colour=x, channel="r", space="rgb") # 获取R通道

get_channel(colour=x, channel="alpha", space="rgb") # 获取透明度

get_channel(colour=x, channel="h", space="hcl") # 由于space="hcl",所以这里的"h"是HCL中的H通道而不是HSV中的H通道

set_channel(colour=x, channel="alpha", value=c(0.4, 0.6, 1, 1), space="rgb") # 在RGB表示法下修改透明度(相当于scales::alpha)

set_channel(colour=x, channel="v", value=c(0.4, 0.6, 1, 1), space="hsv")

三、生成颜色

## 用gray或grey生成不同程度的灰色

y=gray(level=c(0.1, 0.3, 0.5, 0.7), alpha=0.8) # level的取值为0至1, 0代表全黑,1代表全白

showcolor(y)

## 用rainbow生成连续的色盘色

y=rainbow(7)

showcolor(y)

showcolor(rainbow(20)) # 当颜色多时,末端的颜色开始接近红色

showcolor(rainbow(20, start=0, end=2/3)) # 用end将末端设成蓝色(色盘的2/3处是蓝色);当然,开端也可以用start设置

## 在RGB系统下生成多个颜色之间的任意多个渐变色

y=color Ramp Palette(c("blue", "yellow", "red"))(10) # 注意:仅用color Ramp Palette(c("blue", "yellow", "red"))只能生成函数而不能生成颜色

showcolor(y)

color Ramp Palette(c("#ff0000", "#00ff00"))(10) # 用十六进制表示法时,不要加上透明度

## 使用RColor Brewer包中的配色方案

# install.packages("RColor Brewer")

library(RColor Brewer)

brewer.pal.info # 这个数据框包含包中所有成套颜色的信息

y=brewer.pal(6, "Greens") # 提取颜色,n为提取多少颜色(不能多于该套颜色的总颜色数),name为该套颜色的名称

showcolor(y)

## 使用HCL配色方案

# 使用color Ramp Palette函数生成渐变色,并把space参数的值从默认的"rgb"改为"Lab"

y=color Ramp Palette(c("orange", "blue"), space="Lab")(10)

# R自带丰富的HCL配色方案。我们可用hcl.pals函数查看可用配色方案的名称

pal_name=hcl.pals(type=NULL) # type参数的默认值为NULL,代表显示所有配色方案的名称,亦可改为"sequential"(适用于连续变量的颜色)、"qualitative"(适用于离散变量的颜色)、"diverging"(适用于中间值有明确意义的连续变量的颜色)、"divergingx"(适用于连续变量,但在颜色的平衡性方面不如"diverging")

# 如果要使用某个配色方案,则使用hcl.colors函数提取颜色

mycolor=hcl.colors(n=15, palette="Peach") # 在本例中,我们选中了名为"Peach"的配色方案,并用n(n为任意大于等于1的整数)来确定要获取多少颜色

showcolor(mycolor)

# 不过,hcl.pal函数只显示配色方案名称,而不能把配色方案的颜色显示出来。我们用colorspace包中的hcl_palettes函数来直观地查看(但不能提取)这些颜色

check_color=colorspace::hcl_palettes(type="diverging", plot=TRUE, n=8) # type参数的取值与hcl.pals相同,没有"divergingx"这个选项;plot参数此处应设为TRUE,这是因为我们要在图上查看颜色;n为每个配色方案显示的颜色数

## 为数值分配颜色

# 设想我们希望在图表上用绿色点代表最小值,用红色点代表最大值,并用绿色与红色之间的渐变色赋予其他点,此时我们该如何获取颜色?

x=c(1, 2.8, 3)

# 最简单的办法是用color Ramp Palette,这样1得到绿色,3得到绿色,2.8得到绿色与红色中间的颜色

color_1=color Ramp Palette(c("green", "red"), space="Lab")(3)

# 但也许我们想实现的效果是这样的:既然2.8更接近3,那么第2个颜色就不应该正好位于绿色与红色之间,而是应该更偏向红色

library(scales)

f=col_numeric(palette=c("green", "red"), domain=c(1, 3), na.color="#808080") # 用此函数生成的不是最终的颜色,而是可用来对颜色进行加工的另一个函数。参数palette指定颜色,domain指定数值范围。本例中,我们要处理的数值是1、2.8、3,故取最小值和最大值1和3,na.color用于指定缺失值的颜色。最终产生的颜色是位于Lab系统(相当于HCL系统)中的渐变色

color_2=f(x)

## 用RImage Palette包提取画中的主要颜色

# install.packages("RImage Palette")

# install.packages(c("png", "jpeg")) # 这两个包分别用于读取png或jpg格式的图片

library(RImage Palette); library(png); library(jpeg)

# 用png::read PNG读取png图片,用read JPEG读取jpg图片

x=read JPEG("flower.jpg") # 课件中的图片

set.seed(1234) # 为确保每次得到相同的提取结果,需设随机种子

y=image_palette(x, n=10)

showcolor(y) ukKG78imcYvR3Gl/gozKUl3rlnR9F1PJtAldRlBjI04xJe2F9P1NYKRGn6v5xoSS

点击中间区域
呼出菜单
上一章
目录
下一章
×