如何在 R 中创建曲面图

How to create surface plot in R

我目前正在尝试开发一个曲面图来检查以下数据框的结果。我想在 x 轴上绘制噪声的增加值,在 y 轴上绘制 mu 的增加值,在 z 轴上绘制点估计值。在查看 ggplot2 和 ggplotly 之后,我不清楚如何在表面或 3D 图中绘制这些列中的每一列。

 df <-  "mu noise0    noise1     noise2     noise3    noise4    noise5
    1      1  0.000000  0.9549526  0.8908646  0.919630  1.034607
    2      2  1.952901  1.9622004  2.0317115  1.919011  1.645479
    3      3  2.997467  0.5292921  2.8592976  3.034377  3.014647
    4      4  3.998339  4.0042379  3.9938346  4.013196  3.977212
    5      5  5.001337  4.9939060  4.9917115  4.997186  5.009082
    6      6  6.001987  5.9929932  5.9882173  6.015318  6.007156
    7      7  6.997924  6.9962483  7.0118066  6.182577  7.009172
    8      8  8.000022  7.9981131  8.0010066  8.005220  8.024569
    9      9  9.004437  9.0066182  8.9667536  8.978415  8.988935
   10     10 10.006595  9.9987245  9.9949733  9.993018 10.000646"

提前致谢。

ggplot 接受长格式的数据,这意味着您需要 melt 您的数据集,例如使用 reshape2 中的函数包裹:

dfLong = melt(df, 
              id.vars = "mu", 
              variable.name = "noise", 
              value.name = "meas")

结果列 noise 包含 noise0noise1 等条目。您可以提取数字并转换为数字列:

dfLong$noise = with(dfLong, as.numeric(gsub("noise", "", noise)))

这会将您的数据转换为:

   mu noise       meas
1   1     0  1.0000000
2   2     0  2.0000000
3   3     0  3.0000000
...

根据 ggplot documentation:

ggplot2 can not draw true 3D surfaces, but you can use geom_contour(), geom_contour_filled(), and geom_tile() to visualise 3D surfaces in 2D.

因此,例如:

ggplot(dfLong,
   aes(x = noise
       y = mu, 
       fill = meas)) +
geom_tile() +
scale_fill_gradientn(colours = terrain.colors(10))

产生:

这是使用 geom_tile() 的一种方法。首先,您需要将数据框放入更多 Tidy format,目标是包含列:

  • mu:这里没有变化
  • 噪声: 需要将您的“噪声 0”、“噪声 1”、...列组合在一起,并且
  • z: 作为噪声值,我们将使用此列应用 fill= 美学。

为此,我使用了 dplyrgather(),但还有其他方法(melt()pivot_longer() 也可以)。我还添加了一些代码以仅提取“噪声”列的数字部分,然后将其重新格式化为整数以确保您的 x 轴和 y 轴为 numeric/integers:

# assumes that df is your data as data.frame
df <- df %>% gather(key="noise", value="z", -mu)
    df <- df %>% separate(col = "noise", into=c('x', "noise"), sep=5) %>% select(-x)
    df$noise <- as.integer(df$noise)

这是您如何绘制它的示例,但美学取决于您。我决定还包括 geom_text() 以显示 df$z 的实际值,以便我们可以更好地了解发生了什么。另外,我使用 rainbow 是因为“它很漂亮”——你可能想从 RColorBrewer 包中选择一个更合适的定量比较量表。

ggplot(df, aes(x=noise, y=mu, fill=z)) + theme_bw() +
    geom_tile() +
    geom_text(aes(label=round(z, 2))) +
    scale_fill_gradientn(colors = rainbow(5))

编辑: 要回答 OP 的跟进,是的,您也可以通过 plotly 展示这一点。这是一个直接的过渡:

p <- plot_ly(
    df, x= ~noise, y= ~mu, z= ~z,
    type='mesh3d', intensity = ~z,
    colors= colorRamp(rainbow(5))
  )
p

此处为静态图片:

显示这组特定信息的更丰富的方法是通过创建 df$delta_z 来查看 df$zdf$mu 相关的变化,然后使用它来绘制. (您也可以像上面那样通过 ggplot() + geom_tile() 绘图):

df$delta_z <- df$z - df$mu

p1 <- plot_ly(
    df, x= ~noise, y= ~mu, z= ~delta_z,
    type='mesh3d', intensity = ~delta_z,
    colors= colorRamp(rainbow(5))
  )

给你这个(这里是静态图片):