Visualizing 3D Convex Hulls for Grouped Data in R with Plotly

36 views Asked by At

I'm working with a dataset in R that includes various parameters related to agricultural practices and outcomes. Here's a simplified structure of my data frame:

df <- structure(list(peanutSeedToFood = c(1.41896783664886, 1.45277228739953, 
2.45130326046724, 1.05434906990347, 2.5, 1.18856873091444), rotationCycle = c("ThreeYears", 
"ThreeYears", "ThreeYears", "ThreeYears", "ThreeYears", "ThreeYears"), ownFallowUse = c("UseFallowIfNeeded", "UseFallowIfNeeded", 
"UseFallowIfNeeded", "UseFallowIfNeeded", "UseFallowIfNeeded", "NeverUseFallow"), loanStrategy = structure(c(2L, 2L, 1L, 2L, 
1L, 1L), .Label = c("AllExtraParcelsLoaner", "ExtraParcelsExceptFallowLoaner", "Selfish"), class = "factor"), ...), class = "data.frame")

The dataframe includes a factor variable loanStrategy with three levels: "AllExtraParcelsLoaner", "ExtraParcelsExceptFallowLoaner", and "Selfish". I'm interested in visualizing the 3D space occupied by each of these groups based on three continuous variables: objective.lastPopulation, objective.lastEffectiveFallowRatio, and objective.lastMilYield.

I've been able to create a 3D scatter plot using Plotly in R.

 plyply<- plot_ly(df, x=~objective.lastPopulation, 
                  y=~objective.lastMilYield,
                  z=~-objective.lastEffectiveFallowRatio, 
                  color=~loanStrategy, size=~rainFall)
 plyply <- plyply %>%  add_markers()
plyply

enter image description here

But now I want to go a step further and visualize the convex hull that encompasses the points of each group in this 3D space, essentially visualizing the volume occupied by each group.

1

There are 1 answers

0
Stéphane Laurent On

You can use the cxhull package to get a mesh of the convex hull, and you can plot such a mesh with plotly using add_trace with type = "mesh3d".

library(plotly)
library(cxhull)

dat1 <- data.frame(
  x = rgamma(12, 10, 1),
  y = rgamma(12, 10, 1),
  z = rgamma(12, 10, 1)
)
dat2 <- data.frame(
  x = rgamma(12, 15, 1),
  y = rgamma(12, 15, 1),
  z = rgamma(12, 15, 1)
)

hull1 <- cxhull(as.matrix(dat1))
hull2 <- cxhull(as.matrix(dat2))
mesh1 <- hullMesh(hull1)
mesh2 <- hullMesh(hull2)
vertices1 <- mesh1$vertices
faces1 <- mesh1$faces
vertices2 <- mesh2$vertices
faces2 <- mesh2$faces

plot_ly() %>% 
  add_trace(
    x = vertices1[, 1], y = vertices1[, 2], z = vertices1[, 3],
    i = faces1[, 1] - 1, j = faces1[, 2] - 1, k = faces1[, 3] - 1,
    type = "mesh3d",
    opacity = 0.5, color = I("#121212")
  ) %>% 
  add_trace(
    x = vertices2[, 1], y = vertices2[, 2], z = vertices2[, 3],
    i = faces2[, 1] - 1, j = faces2[, 2] - 1, k = faces2[, 3] - 1,
    type = "mesh3d",
    opacity = 0.5, color = I("#121212")
  )

However it seems that the color argument has no effect.