R plot3d颜色渐变图例

Posted

技术标签:

【中文标题】R plot3d颜色渐变图例【英文标题】:R plot3d color gardient legend 【发布时间】:2019-08-09 02:25:33 【问题描述】:

我有一个 3D 图,其中的点根据一些额外的向量进行着色。我的问题是添加颜色渐变图例。这是我的代码:

x           = matrix(NA,100,6)
#x value
x[,1]       = runif(100, 0, 10)
#y value
x[,2]       = runif(100, 0, 10)
#z value
x[,3]       = x[,1]+x[,2]
#additional value
x[,4]       = runif(100, 0, 1)

#find out in which interval each additional value is
intervals   = seq(0,1,1/10)
x[,5]       = findInterval(x[,4], intervals)

colours     = topo.colors(length(intervals))

x[,6]       = colours[x[,5]]

library(rgl)

plot3d(as.numeric(x[,1]),as.numeric(x.stab.in[,2]), as.numeric(x[,3]), 
       type="p", col=x[,6], size=2, xlab = "x(t)", ylab = "y(t)",
       zlab = "z(t)")
decorate3d(xlab = "x", ylab = "y", zlab = "z")
legend3d("topright", legend = intervals, pch = 16, col = colours, cex=1, inset=c(0.02))
grid3d(c("x", "y+", "z"),col = "gray")

剧情是这样的

但我想要渐变形式的图例。这意味着我不希望每种颜色都有单独的点,而是需要一个颜色相互淡入的盒子。

【问题讨论】:

【参考方案1】:

如果您想在交互式 3d 绘图上绘制渐变,例如您需要将绘图动画化成电影,这是另一种解决方案。

require(car)
require(rgl)
require(RColorBrewer)
require(mgcv)
require(magick) #Only for creating the animation of the plot as a gif

#Creating mock dataset
  Example_Data <- data.frame(Axis1 = rnorm(100),
                             Axis2 = rnorm(100),
                             Axis3 = rnorm(100))
  
  Example_Data$Value <- Example_Data$Axis1+Example_Data$Axis2

#Defining function that takes a vector of numeric values and converts them to
#a spectrum of rgb colors to help color my scatter3d plot
  get_colors <- function(values)
    v <- (values - min(values))/diff(range(values))
    x <- colorRamp(rev(brewer.pal(11, "Spectral")))(v)
    rgb(x[,1], x[,2], x[,3], maxColorValue = 255)
  
  
#Writing function that takes a vector of numeric values and a title and creates
#a gradient legend based on those values and the title and suitable for addition
#to a scatter3d plot via a call to bgplot3d()
#Note, I didn't have time to make this automatically adjust text position/size for different size
#plot windows, so values may need to be adjusted manually depending on the size of the plot window.
  gradient_legend_3d <- function(values, title)
    min_val <- min(values)
    max_val <- max(values)
    x <- colorRamp(brewer.pal(11, "Spectral"))((0:20)/20)
    colors <- rgb(x[,1], x[,2], x[,3], maxColorValue = 255)
    legend_image <- as.raster(matrix(colors, ncol=1))
    plot(c(0,1),c(0,1),type = 'n', axes = F,xlab = '', ylab = '', main = '') #Generates a blank plot
    text(x=0.92, y = seq(0.5, 1,l=5), labels = signif(seq(min_val, max_val,l=5), 2), cex = 1.5) #Creates the numeric labels on the scale
    text(x = 0.85, y = 1, labels = title, adj = 1, srt = 90, cex = 1.5) #Determines where the title is placed
    rasterImage(legend_image, 0.87, 0.5, 0.9,1) #Values can be modified here to alter where and how wide/tall the gradient is drawn in the plotting area
  
  
#Creating scatter3d plot
  scatter3d(x = Example_Data$Axis1, y = Example_Data$Axis2, z = Example_Data$Axis3, xlab = "Axis1", ylab = "Axis2", zlab = "Axis3", surface = F, grid = F, ellipsoid = F, fogtype = "none", point.col = get_colors(Example_Data$Value))

#Changing size of plotting window and orientation to optimize for addition of static legend
#This may not work on another machine, so the window may need to be adjusted manually
  par3d(windowRect = c(0,23,1536,824))
  par3d(userMatrix = matrix(c(-0.98181450, -0.02413967, 0.18830180, 0, -0.03652956, 0.99736959, -0.06260729, 0, -0.18629514, -0.06834736, -0.98011345, 0, 0, 0, 0, 1), nrow = 4, ncol = 4, byrow = T))
  
#Adding legend
  bgplot3d(gradient_legend_3d(Example_Data$Value, "Point Value"))
  
#Animating plot and saving as gif
  movie3d(spin3d(axis = c(0,1,0), rpm = 5), duration = 12, dir = getwd(), fps = 5, convert = FALSE, clean = FALSE)
  frames <- NULL
  for(j in 0:60)
    if(j == 1)
      frames <- image_read(sprintf("%s%03d.png", "movie", j))
     else 
      frames <- c(frames, image_read(sprintf("%s%03d.png", "movie", j)))
    
  
  animation <- image_animate(frames, fps = 10, optimize = TRUE)
  image_write(animation, path = "Example.gif")
  for(j in 0:60)
   unlink(sprintf("%s%03d.png", "movie", j))
  
  

查看此代码生成的 3d 图的链接: gif of 3d plot with gradient color scale

【讨论】:

【参考方案2】:

如果您可以使用scatterplot3d 包而不是rgl,这是一个可能的解决方案。它基本相同,但非交互式。这是您修改后的代码以产生您的预期结果。

x           = matrix(NA,100,6)
#x value
x[,1]       = runif(100, 0, 10)
#y value
x[,2]       = runif(100, 0, 10)
#z value
x[,3]       = x[,1]+x[,2]
#additional value
x[,4]       = runif(100, 0, 1)

#find out in which interval each additional value is
intervals   = seq(0,1,1/10)
x[,5]       = findInterval(x[,4], intervals)

#produce gradient of colors
#you can define different colors (two or more)
gradient <- colorRampPalette(colors = c("yellow", "green", "blue"))
colours <- gradient(length(intervals))

x[,6]       = colours[x[,5]]

library(scatterplot3d)
png('3d.png', width = 600, height = 400)
layout(matrix(1:2, ncol=2), width = c(3, 1), height = c(1, 1))
scatterplot3d(as.numeric(x[,1]),as.numeric(x[,2]), as.numeric(x[,3]), type = 'p',
       cex.symbols = 1.25, color=x[,6], pch = 16, xlab = "x(t)", ylab = "y(t)", zlab = "z(t)")
plot(x = rep(1, 100), y = seq_along(x[,6]), 
     pch = 15, cex = 2.5, 
     col = gradient(length(x[,6])), 
     ann = F, axes = F, xlim = c(1, 2))
axis(side = 2, at = seq(1, nrow(x), length.out = 11), 
     labels = 1:11,
     line = 0.15)
dev.off()

这将绘制以下图表

【讨论】:

这正是我想要的。谢谢!有没有办法让颜色渐变更宽?我尝试使用更高的 cex 值,但随后渐变延伸到轴上。 我找到了解决方案。我使用了更高的 cex 值并添加了 xaxs="i", yaxs="i"

以上是关于R plot3d颜色渐变图例的主要内容,如果未能解决你的问题,请参考以下文章

R语言ggplot2可视化热力图(heatmap)自定义配置图例标签为百分比进行热力图颜色渐变显示(legend to display percentage sign)

ggplot 将颜色渐变缩放到数据范围之外

R中的2d颜色渐变图

在R闪亮中将fileinput进度条颜色更改为渐变

如何在R中制作渐变颜色填充时间序列图

ggplot2:使用填充geom_bar指定颜色时缺少图例