本节将介绍如何在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)