I'm trying to smooth a 11 X 8 matrix and I can't seem to find a way to do this. I know there are several threads on this but none has helped for my situation. Every approach I've found requires some sort of z ~ x*y approach. In my case I just have a matrix that I would like to simply smooth all of the cell entries to make a smoother surface plot.
m
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 29.02530 28.57123 39.02334 38.25483 29.59624 65.01706 41.04771 98.62005
[2,] 24.46539 24.08265 32.89272 32.24494 24.94663 54.80279 34.59906 83.12670
[3,] 28.30679 27.86395 38.05733 37.30784 28.86359 63.40758 40.03159 96.17873
[4,] 24.99883 24.60774 33.60991 32.94800 25.49056 55.99770 35.35345 84.93918
[5,] 24.63308 24.24771 33.11817 32.46595 25.11761 55.17842 34.83621 83.69646
[6,] 29.85776 29.39066 40.14254 39.35199 30.44506 66.88177 42.22497 101.44850
[7,] 18.54275 18.25267 24.92998 24.43901 18.90749 41.53601 26.22324 63.00320
[8,] 24.43846 24.05615 32.85652 32.20945 24.91917 54.74248 34.56098 83.03522
[9,] 27.09827 26.67434 36.43252 35.71503 27.63130 60.70048 38.32249 92.07251
[10,] 37.11375 36.53313 49.89792 48.91525 37.84378 83.13528 52.48642 126.10236
[11,] 26.06763 25.65982 35.04686 34.35666 26.58038 58.39182 36.86495 88.57066
library(lattice)
wireframe(m)
any ideas?
Whatever you end up doing, you'll need some model to smooth the data you have. You could use a wide range of models to do the smoothing but the one I am most familiar with is the penalised regression spline approach to fitting GAMs via the mgcv package, which also happens to come with R.
Firs, some simulated data
set.seed(1)
m <- matrix(runif(11*8), ncol = 8)
To model these, you need them in the form z ~ x + y
, i.e. long format where there is a row for every z
(cell in your matrix). So, arrange our example data into long format
df <- data.frame(x = rep(seq_len(ncol(m)), each = nrow(m)),
y = rep(seq_len(nrow(m)), times = ncol(m)),
z = c(m))
> head(df)
x y z
1 1 1 0.2655087
2 1 2 0.3721239
3 1 3 0.5728534
4 1 4 0.9082078
5 1 5 0.2016819
6 1 6 0.8983897
Here x
varies slowest and refers to the columns, y
fastest and refers to the rows. Next load mgcv and fit the model
require("mgcv")
mod <- gam(z ~ te(x, y), data = df)
The model is a 2d tensor product spline of the x
and y
"locations`.
To replicate your plot, but smoother, take the fitted values of the model and arrange as a matrix again
m2 <- matrix(fitted(mod), ncol = 8)
Then plot
require("lattice")
wireframe(m2)
Depending on what you are doing, you can control the degree of smoothness via two options to te()
:
k
sets the degrees of freedom or complexity of the smooths. Here is really sets the initial dimensions of the basis functions, which are then shrunk to some "optimal dimensionality via the penalised regression. For the tensor product spline fitted viate()
, you can specifyk
for both dimensions of the spline. To setk = 5
in both directions usete(x, y, k = 5)
. To have different basis dimensions usete(x, y, k = c(10,5))
for example to have dimension 10 basis functions forx
and dimension 5 fory
.Fix the degrees of freedom, i.e. don't do any of the penalisation I mentioned above. You do this by adding
fx = TRUE
to thete()
call. To continue the last example,te(x, y, k = c(10,5), fx = TRUE)
will use the basis functions as above but won't shrink down from this to some smaller number of degrees of freedom.
来源:https://stackoverflow.com/questions/20848740/smoothing-surface-plot-from-matrix