1

I am trying to build a surface plot in R of data with gridded x and y axes. The x-axis varies from 1 through 8, while y-axis varies from -4 through 4.

Here are the data for the plot :

   -4  -3  -2  -1   0   1   2  3   4
1 159 144 133 132 138 123  80 28 -22
2 153 135 121 122 160 162 110 50  -7
3 148 126 107 104 161 190 135 67   3
4 145 120  96  92 161 202 149 77   8
5 144 117  92  89 161 205 153 80  10
6 145 120  96  92 161 202 149 77   8
7 148 126 107 104 161 190 135 67   3
8 153 135 121 122 160 162 110 50  -7
9 159 144 133 132 138 123  80 28 -22

Any help will be highly appreciated.

Amit Verma
  • 40,709
  • 21
  • 93
  • 115
  • Please make your [question reproducible](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). Also show what you've tried so far. – Roman Luštrik Nov 17 '14 at 09:02
  • 1
    When people improve your post content by properly formatting code and correcting typos, please don't replace it with the original content. – jbaums Nov 17 '14 at 09:25
  • 1
    Many thanks for the improvement. I was trying to make the data appear like this but was not able to. So this was extremely pleasing gesture from you @jbaums! Thanks! – Prasanna dahal Nov 17 '14 at 10:35
  • @RomanLuštrik, I had tried excel graphs and the results were just fine. I was, however, unable to modify too much, like add more contour lines to it. As I said, I am very new to R and haven't come anywhere near the level to discuss any progress (or even the lack of it). – Prasanna dahal Nov 17 '14 at 15:47

1 Answers1

5

Either latticeExtra::wireframe or rgl::persp3d can plot 3D surface plots.

z <- as.matrix(read.table(text='-4  -3  -2  -1   0   1   2  3   4
1 159 144 133 132 138 123  80 28 -22
2 153 135 121 122 160 162 110 50  -7
3 148 126 107 104 161 190 135 67   3
4 145 120  96  92 161 202 149 77   8
5 144 117  92  89 161 205 153 80  10
6 145 120  96  92 161 202 149 77   8
7 148 126 107 104 161 190 135 67   3
8 153 135 121 122 160 162 110 50  -7
9 159 144 133 132 138 123  80 28 -22', header=TRUE, check.names=FALSE))

First, with latticeExtra:

library(latticeExtra)
wireframe(z, scales=list(arrows=FALSE), xlab='x', ylab='y', drape=TRUE,
          col.regions=terrain.colors(10), at=seq(min(z), max(z), len=11))

enter image description here

See ?wireframe for details on how to specify the viewing angle.

Alternatively, persp3d from the rgl package can generate 3D surfaces that can be rotated/zoomed with the mouse.

library(rgl)
persp3d(1:9, -4:4, z, col = "lightblue", xlab='x', ylab='y')

You could also consider a heatmap/levelplot for this:

lattice::levelplot(z, col.regions=terrain.colors, xlab='x', ylab='y', 
          scales=list(tck=1:0))

enter image description here


EDIT

You can use akima to interpolate your data if you want to increase the resolution of the plots.

For example:

library(akima)

xyz <- transform(expand.grid(x=as.numeric(rownames(z)), 
                             y=as.numeric(colnames(z))), z=c(z))

z_interp <- interp(xyz$x, xyz$y, xyz$z)

xyz_interp <- transform(expand.grid(x=z_interp$x, y=z_interp$y), z=c(z_interp$z))

wireframe(z ~ x * y, data=xyz_interp, scales=list(arrows=FALSE),
          drape=TRUE, col.regions=terrain.colors(10), 
          at=seq(min(xyz_interp$z), max(xyz_interp$z), len=11))

enter image description here

Control the interpolated resolution with arguments xo and yo to interp.

jbaums
  • 27,115
  • 5
  • 79
  • 119
  • Thanks a ton! I love the heat map idea just as well! But the resolution seems too poor, because of my data I guess. Even the surface plot isn't looking aesthetically great because of lack of finer values. Is there a way we can get around this problem and create a more continuous looking plot? – Prasanna dahal Nov 17 '14 at 15:41