R Markdown

#Basic 3D scatter plots

##library("scatterplot3d") # load
data(iris)
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
# Example data
x <- c(1, 2, 3, 4, 5)
y <- c(2, 3, 4, 5, 6)
z <- c(3, 4, 5, 6, 7)

# Check if lengths are equal
if (length(x) == length(y) && length(y) == length(z)) {
  # Plot the scatterplot
  library(scatterplot3d)
  scatterplot3d(x, y, z, main="3D Scatterplot")
} else {
  # Print an error message if lengths differ
  stop("Lengths of 'x', 'y', and 'z' must be the same.")
}

scatterplot3d(iris[,1:3])

scatterplot3d(iris[,1:3], angle = 55)

Change the main title and axis labels

scatterplot3d(iris[,1:3],
              main="3D Scatter Plot",
              xlab = "Sepal Length (cm)",
              ylab = "Sepal Width (cm)",
              zlab = "Petal Length (cm)")

# Change the shape and the color of points

scatterplot3d(iris[,1:3], pch = 16, color="steelblue")

Change point shapes by groups

shapes = c(16, 17, 18) 
shapes <- shapes[as.numeric(iris$Species)]
scatterplot3d(iris[,1:3], pch = shapes)

# Change point colors by groups

colors <- c("#999999", "#E69F00", "#56B4E9")
colors <- colors[as.numeric(iris$Species)]
scatterplot3d(iris[,1:3], pch = 16, color=colors)

# Change the global appearance of the graph

Remove the box around the plot

scatterplot3d(iris[,1:3], pch = 16, color = colors,
              grid=TRUE, box=FALSE)

Add grids on the different factes of scatterplot3d graphics:

# 1. Source the function
source('http://www.sthda.com/sthda/RDoc/functions/addgrids3d.r')
# 2. 3D scatter plot
scatterplot3d(iris[, 1:3], pch = 16, grid=FALSE, box=FALSE)
# 3. Add grids
addgrids3d(iris[, 1:3], grid = c("xy", "xz", "yz"))

Add bars

scatterplot3d(iris[,1:3], pch = 16, type="h", 
              color=colors)

# Add legends

Specify the legend position using xyz.convert()

s3d <- scatterplot3d(iris[,1:3], pch = 16, color=colors)
legend(s3d$xyz.convert(7.5, 3, 4.5), legend = levels(iris$Species),
      col =  c("#999999", "#E69F00", "#56B4E9"), pch = 16)

Specify the legend position using keywords

# "right" position
s3d <- scatterplot3d(iris[,1:3], pch = 16, color=colors)
legend("right", legend = levels(iris$Species),
      col =  c("#999999", "#E69F00", "#56B4E9"), pch = 16)

# Use the argument inset
s3d <- scatterplot3d(iris[,1:3], pch = 16, color=colors)
legend("right", legend = levels(iris$Species),
  col = c("#999999", "#E69F00", "#56B4E9"), pch = 16, inset = 0.1)

# "bottom" position
s3d <- scatterplot3d(iris[,1:3], pch = 16, color=colors)
legend("bottom", legend = levels(iris$Species),
      col = c("#999999", "#E69F00", "#56B4E9"), pch = 16)

# Customize the legend position

# Custom point shapes
s3d <- scatterplot3d(iris[,1:3], pch = shapes)
legend("bottom", legend = levels(iris$Species),
       pch = c(16, 17, 18), 
      inset = -0.25, xpd = TRUE, horiz = TRUE)

# Custom colors
s3d <- scatterplot3d(iris[,1:3], pch = 16, color=colors)
legend("bottom", legend = levels(iris$Species),
      col =  c("#999999", "#E69F00", "#56B4E9"), pch = 16, 
      inset = -0.25, xpd = TRUE, horiz = TRUE)

# Custom shapes/colors
s3d <- scatterplot3d(iris[,1:3], pch = shapes, color=colors)
legend("bottom", legend = levels(iris$Species),
      col =  c("#999999", "#E69F00", "#56B4E9"), 
      pch = c(16, 17, 18), 
      inset = -0.25, xpd = TRUE, horiz = TRUE)

# Add point labels

scatterplot3d(iris[,1:3], pch = 16, color=colors)
text(s3d$xyz.convert(iris[, 1:3]), labels = rownames(iris),
     cex= 0.7, col = "steelblue")

# Add regression plane and supplementary points

data(trees)
head(trees)
##   Girth Height Volume
## 1   8.3     70   10.3
## 2   8.6     65   10.3
## 3   8.8     63   10.2
## 4  10.5     72   16.4
## 5  10.7     81   18.8
## 6  10.8     83   19.7

3D scatter plot with the regression plane:

# 3D scatter plot
s3d <- scatterplot3d(trees, type = "h", color = "blue",
    angle=55, pch = 16)
# Add regression plane
my.lm <- lm(trees$Volume ~ trees$Girth + trees$Height)
s3d$plane3d(my.lm)
# Add supplementary points
s3d$points3d(seq(10, 20, 2), seq(85, 60, -5), seq(60, 10, -10),
    col = "red", type = "h", pch = 8)

## Install plot3D package

#install.packages("plot3D")

Load plot3D package

library("plot3D")
## Warning: package 'plot3D' was built under R version 4.3.2

Prepare the data

data(iris)
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa

Basic scatter plot

scatter3D(x, y, z, clab = c("Sepal", "Width (cm)"))

scatter3D(x, y, z, colvar = NULL, col = "blue",
          pch = 19, cex = 0.5)

# Change the type of the box around the plot

# full box
scatter3D(x, y, z, bty = "f", colkey = FALSE, main ="bty= 'f'")

# back panels and grid lines are visible
scatter3D(x, y, z, bty = "b2", colkey = FALSE, main ="bty= 'b2'" )

# grey background with white grid lines
scatter3D(x, y, z, bty = "g", colkey = FALSE, main ="bty= 'g'")

# User defined
scatter3D(x, y, z, pch = 18, bty = "u", colkey = FALSE, 
   main ="bty= 'u'", col.panel ="steelblue", expand =0.4, 
   col.grid = "darkblue")

# Color palettes

# gg.col: ggplot2 like color
scatter3D(x, y, z, bty = "g", pch = 18, col = gg.col(100))

# ramp.col: custom palettes
scatter3D(x, y, z, bty = "g", pch = 18,
          col = ramp.col(c("blue", "yellow", "red")) )

# Change the color by groups

scatter3D(x, y, z, bty = "g", pch = 18, 
          col.var = as.integer(iris$Species), 
          col = c("#1B9E77", "#D95F02", "#7570B3"),
          pch = 18, ticktype = "detailed",
          colkey = list(at = c(2, 3, 4), side = 1, 
          addlines = TRUE, length = 0.5, width = 0.5,
          labels = c("setosa", "versicolor", "virginica")) )

# Change the position of the legend

# Bottom colkey
scatter3D(x, y, z, bty = "g",
          colkey = list(side = 1, length = 0.5))

# 3D viewing direction

scatter3D(x, y, z, theta = 15, phi = 20)

scatter3D(x, y, z, phi = 0, bty ="g")

# Titles and axis labels

scatter3D(x, y, z, pch = 18,  theta = 20, phi = 20,
          main = "Iris data", xlab = "Sepal.Length",
          ylab ="Petal.Length", zlab = "Sepal.Width")

# Tick marks and labels

 scatter3D(x, y, z, phi = 0, bty = "g",
        pch = 20, cex = 2, ticktype = "detailed")

# Add points and text to an existing plot

# Create a scatter plot
 scatter3D(x, y, z, phi = 0, bty = "g",
        pch = 20, cex = 2, ticktype = "detailed")
# Add another point (black color)
scatter3D(x = 7, y = 3, z = 3.5, add = TRUE, colkey = FALSE, 
         pch = 18, cex = 3, col = "black")

Line plots

# type ="l" for lines only
 scatter3D(x, y, z, phi = 0, bty = "g", type = "l", 
           ticktype = "detailed", lwd = 4)

# type ="b" for both points and lines
 scatter3D(x, y, z, phi = 0, bty = "g", type = "b", 
           ticktype = "detailed", pch = 20, 
           cex = c(0.5, 1, 1.5))

# type ="h" for vertical lines
scatter3D(x, y, z, phi = 0, bty = "g",  type = "h", 
           ticktype = "detailed", pch = 19, cex = 0.5)

# Add confidence interval

# Confidence interval
CI <- list(z = matrix(nrow = length(x),
                    data = rep(0.1, 2*length(x))))
head(CI$z)
##      [,1] [,2]
## [1,]  0.1  0.1
## [2,]  0.1  0.1
## [3,]  0.1  0.1
## [4,]  0.1  0.1
## [5,]  0.1  0.1
# 3D Scatter plot with CI
scatter3D(x, y, z, phi = 0, bty = "g", col = gg.col(100), 
          pch = 18, CI = CI)

# 3D fancy Scatter plot with small dots on basal plane

# Add small dots on basal plane and on the depth plane
scatter3D_fancy <- function(x, y, z,..., colvar = z)
  {
   panelfirst <- function(pmat) {
      XY <- trans3D(x, y, z = rep(min(z), length(z)), pmat = pmat)
      scatter2D(XY$x, XY$y, colvar = colvar, pch = ".", 
              cex = 2, add = TRUE, colkey = FALSE)
   
      XY <- trans3D(x = rep(min(x), length(x)), y, z, pmat = pmat)
      scatter2D(XY$x, XY$y, colvar = colvar, pch = ".", 
              cex = 2, add = TRUE, colkey = FALSE)
  }
  scatter3D(x, y, z, ..., colvar = colvar, panel.first=panelfirst,
    colkey = list(length = 0.5, width = 0.5, cex.clab = 0.75)) 
}

Fancy scatter plot:

scatter3D_fancy(x, y, z, pch = 16,
    ticktype = "detailed", theta = 15, d = 2,
    main = "Iris data",  clab = c("Petal", "Width (cm)") )

# Regression plane

data(mtcars)
head(mtcars[, 1:6])
##                    mpg cyl disp  hp drat    wt
## Mazda RX4         21.0   6  160 110 3.90 2.620
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875
## Datsun 710        22.8   4  108  93 3.85 2.320
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215
## Hornet Sportabout 18.7   8  360 175 3.15 3.440
## Valiant           18.1   6  225 105 2.76 3.460
# x, y, z variables
x <- mtcars$wt
y <- mtcars$disp
z <- mtcars$mpg
# Compute the linear regression (z = ax + by + d)
fit <- lm(z ~ x + y)
# predict values on regular xy grid
grid.lines = 26
x.pred <- seq(min(x), max(x), length.out = grid.lines)
y.pred <- seq(min(y), max(y), length.out = grid.lines)
xy <- expand.grid( x = x.pred, y = y.pred)
z.pred <- matrix(predict(fit, newdata = xy), 
                 nrow = grid.lines, ncol = grid.lines)
# fitted points for droplines to surface
fitpoints <- predict(fit)
# scatter plot with regression plane
scatter3D(x, y, z, pch = 18, cex = 2, 
    theta = 20, phi = 20, ticktype = "detailed",
    xlab = "wt", ylab = "disp", zlab = "mpg",  
    surf = list(x = x.pred, y = y.pred, z = z.pred,  
    facets = NA, fit = fitpoints), main = "mtcars")

data(USArrests)
with(USArrests, text3D(Murder, Assault, Rape, 
  labels = rownames(USArrests), colvar = UrbanPop, 
  col = gg.col(100), theta = 60, phi = 20,
  xlab = "Murder", ylab = "Assault", zlab = "Rape", 
  main = "USA arrests", cex = 0.6, 
  bty = "g", ticktype = "detailed", d = 2,
  clab = c("Urban","Pop"), adj = 0.5, font = 2))

# text3D and scatter3D

# Plot texts
with(USArrests, text3D(Murder, Assault, Rape, 
  labels = rownames(USArrests), colvar = UrbanPop, 
  col = gg.col(100), theta = 60, phi = 20,
  xlab = "Murder", ylab = "Assault", zlab = "Rape", 
  main = "USA arrests", cex = 0.6, 
  bty = "g", ticktype = "detailed", d = 2,
  clab = c("Urban","Pop"), adj = 0.5, font = 2))
# Add points
 with(USArrests, scatter3D(Murder, Assault, Rape - 1, 
    colvar = UrbanPop, col = gg.col(100), 
    type = "h", pch = ".", add = TRUE))

# Zoom near origin: choose suitable ranges
 plotdev(xlim = c(0, 10), ylim = c(40, 150), 
         zlim = c(7, 25))

hist3D (x = 1:5, y = 1:4, z = VADeaths,
        bty = "g", phi = 20,  theta = -60,
        xlab = "", ylab = "", zlab = "", main = "VADeaths",
        col = "#0072B2", border = "black", shade = 0.8,
        ticktype = "detailed", space = 0.15, d = 2, cex.axis = 1e-9)
# Use text3D to label x axis
 text3D(x = 1:5, y = rep(0.5, 5), z = rep(3, 5),
       labels = rownames(VADeaths),
       add = TRUE, adj = 0)
# Use text3D to label y axis
 text3D(x = rep(1, 4),   y = 1:4, z = rep(0, 4),
       labels  = colnames(VADeaths),
       add = TRUE, adj = 1)

scatter2D: 2D scatter plot

# x, y coordinates
set.seed(1234)
x  <- sort(rnorm(10)) 
y  <- runif(10)
# Variable for coloring points
col.v <- sqrt(x^2 + y^2) 

Basic 2D scatter plot:

scatter2D(x, y, colvar = col.v, pch = 16, bty ="n",
          type ="b")

# 2D scatter plot with confidence interval:

# Confidence interval for x variable only
CI <- list()
CI$x <- matrix(nrow = length(x), data = c(rep(0.25, 2*length(x))))
scatter2D(x, y, colvar = col.v, pch = 16, bty ="n", cex = 1.5, 
          CI = CI, type = "b")

# Confidence interval for both x and y variables
CI$y <- matrix (nrow = length(y), data = c(rep(0.05, 2*length(y))))
CI$col <- "black"
scatter2D(x, y, colvar = col.v, pch = 16,  bty ="n", cex = 1.5,
          CI = CI, type ="b")

CI$y[c(2,4,8,10), ] <- NA  # Some points have no CI
CI$x[c(2,4,8,10), ] <- NA  # Some points have no CI
CI$alen <- 0.02            # increase arrow head
scatter2D(x, y, colvar = col.v, pch = 16,  bty ="n", cex = 1.5,
          CI = CI, type ="b")

# text2D

# Only text
with(USArrests, text2D(x = Murder, y = Assault + 5, colvar = Rape, 
     xlab = "Murder", ylab = "Assault", clab = "Rape", 
     main = "USA arrests", labels = rownames(USArrests), cex = 0.6, 
     adj = 0.5, font = 2))

# text with point
 with(USArrests, text2D(x = Murder, y = Assault + 5, colvar = Rape, 
     xlab = "Murder", ylab = "Assault", clab = "Rape", 
     main = "USA arrests", labels = rownames(USArrests), cex = 0.6, 
     adj = 0.5, font = 2))
 with(USArrests, scatter2D(x = Murder, y = Assault, colvar = Rape, 
     pch = 16, add = TRUE, colkey = FALSE))

2D arrows:

3D rectangle

rect3D(x0 = 0, y0 = 0.5, z0 = 0, x1 = 1, z1 = 5, 
       ylim = c(0, 1), bty = "g", facets = TRUE, 
       border = "red", col ="#7570B3", alpha=0.5,
       lwd = 2, phi = 20)

# 2D rectangle:

rect2D(x0 = runif(3), y0 = runif(3), 
       x1 = runif(3), y1 = runif(3), colvar = 1:3, 
       alpha = 0.4, lwd = 2, main = "rect2D")

Install and load required packages

#install.packages(c("rgl", "car"))
library("car")
## Warning: package 'car' was built under R version 4.3.2
## Loading required package: carData

Prepare the data

data(iris)
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
#rgl.postscript("plot.pdf",fmt="pdf")

Install the RGL package

#install.packages("rgl")

Load the RGL package

library("rgl")
## Warning: package 'rgl' was built under R version 4.3.2

Prepare the data

data(iris)
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa