Search code examples
rrgl

How to use plot3d/surface3d (or another function?) to plot 4d function ("fourth dimension" denoted by color scale)?


I would like to plot: production.ts(31, .002, 10,12,125313.93,211,95,x,"2014-02-01","2014-05-14",z,y) as function of x,y,z

As something like this plot from Mathematica, (if possible in R): https://i.sstatic.net/3PRaf.png

I have a function:

library("lubridate"); library("rgl")

production.ts <- function(a, b, z, c, d, e, 
                    f, g, h, j, r, k) {
  elapsed <- (4-z)*10 + (4-c)
  un.days <- 100 - elapsed
  gone.days <- day(as.Date(h))
  rem.days <- day(as.Date(j))
  r.days <- as.numeric(as.Date(j) - as.Date(h))

  m.r <- f/100*d
  inputs <- d * a * (gone.days - 1)/365 + r
  prin <- m.r + inputs 
  costs <- (r.days/365 * r + 1) * prin 
  added.p <- a/100*d + r 
  due <- d * 1-un.days
  tomr.f <- 1- due + k^2
  acct.paid <- (d - due)*tomr.f
  net <- added.p + due + acct.paid
  pv.net <- net/(1+r*(e-30-day(as.Date(j)))/365)
  end <- d - due - acct.paid
  more.add.p <- end*a*(rem.days-1)/365
  rem <- (f-g)/100 * end
  total.fv <- pv.net + rem + more.add.p 
  out <- costs - total.fv

  out 
}


x<-seq(-10,10,by=.1)
y<-seq(0,1000,by=.1)
z<-seq(0,90,by=.1)

I have tried: func.3d<-Vectorize(production.ts(31, .002, 10,12,125313.93,211,95,x,"2014-02-01","2014-05-14",z,y))

c <- func.3d; c <- cut(c,breaks=64); cols <- rainbow(64)[as.numeric(c)]

open3d()
plot3d(x, y, z, col=cols,type="s",size=1)

But this plots lines and the colors don't line up with the values the function should output.

Does anyone know how I could do this? Thanks, I really appreciate your time!


Solution

  • Like this?

    x<-seq(-10,10,length=100)
    y<-seq(0,1000,length=100)
    z<-seq(0,90,length=100)
    df <- expand.grid(x=x,y=y,z=z)
    
    f <- function(x,y,z) {production.ts(31, .002, 10,12,125313.93,211,95,x,"2014-02-01","2014-05-14",z,y)}
    df$c <- f(df$x,df$y,df$z)
    c <- cut(df$c,breaks=64)
    cols <- rainbow(64)[as.numeric(c)]
    open3d()
    plot3d(df$x, df$y, df$z, col=cols,type="p",size=1)
    

    Your code was not plotting lines. When you pass x, y, and z like that to plot3d(...) it cycles through all the elements together, so x[1],y[1],z[1] is a point, x[2],y[2],z[2] is another point, and so on. Since the vectors are different lengths, the shorter ones are recycled to fill out to the length of the longest. The visual effect of this is that the points lie on a line.

    You want yo plot every combination of x, y, and z, and give each point a color based on that combination. The code above does that. The plot does not quite look like yours, but I can't tell if that is because of the way you have defined your function.

    Also, the way you defined x, y, and z there would be 201 X 10001 X 901 = 1,811,191,101 points, which is too many to handle. The code above plots 1,000,000 points.

    Finally, plotting spheres (type="s") is very expensive and unnecessary in this case.