Hello list, I've been working on this problem for a while and I haven't been able to come up with a solution. I have a couple of functions that plot a bunch of data, then a single point on top of it. What I want is to be able to change the plot of the point without replotting all the data. Consider the following example: x = rnorm(100,1,0.5) y = rnorm(100,1,0.5) plot(x,y,pch=16) points(x[35],y[35],pch=19,col=6,cex=3) What I want to be able to do is to change the purple point to a different value without replotting everything. I know this seems like an odd suggestion, but it comes up a lot with the work I'm doing. I've prepared a package on CRAN called ResearchMethods for a course I'm working on, and there are several functions in there who's GUIs could work better if I could figure this out. If anyone has any ideas, or needs some further explanation, feel free to contact me. Thanks a lot, Sam Stewart
Changing a plot
7 messages · R Help, Ben Bolker, Adaikalavan Ramasamy +2 more
R Help <rhelp.stats <at> gmail.com> writes:
Hello list, I've been working on this problem for a while and I haven't been able to come up with a solution. I have a couple of functions that plot a bunch of data, then a single point on top of it. What I want is to be able to change the plot of the point without replotting all the data. Consider the following example: x = rnorm(100,1,0.5) y = rnorm(100,1,0.5) plot(x,y,pch=16) points(x[35],y[35],pch=19,col=6,cex=3) What I want to be able to do is to change the purple point to a different value without replotting everything.
R's default (base) graphics model is a 'canvas' -- things get drawn, but nothing ever gets erased. (The cheap solution is to overplot in the background color, but that won't work if there's stuff underneath the point that you want to preserve.) You probably need to move to the grid graphics package (hint: buy or borrow Paul Murrell's book) to do something like this. Ben Bolker
One way is to keep a copy of the original and then return to it when you
need it.
x <- rnorm(100,1,0.5)
y <- rnorm(100,1,0.5)
plot(x,y,pch=16)
original <- recordPlot()
for( i in 1:10 ){
points( x[i], y[i], pch=19, col="yellow", cex=3)
points( x[i], y[i], pch=16)
Sys.sleep(1) # slow the graphs a bit
replayPlot(original)
}
Regards, Adai
R Help wrote:
Hello list, I've been working on this problem for a while and I haven't been able to come up with a solution. I have a couple of functions that plot a bunch of data, then a single point on top of it. What I want is to be able to change the plot of the point without replotting all the data. Consider the following example: x = rnorm(100,1,0.5) y = rnorm(100,1,0.5) plot(x,y,pch=16) points(x[35],y[35],pch=19,col=6,cex=3) What I want to be able to do is to change the purple point to a different value without replotting everything. I know this seems like an odd suggestion, but it comes up a lot with the work I'm doing. I've prepared a package on CRAN called ResearchMethods for a course I'm working on, and there are several functions in there who's GUIs could work better if I could figure this out. If anyone has any ideas, or needs some further explanation, feel free to contact me. Thanks a lot, Sam Stewart
______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
R Help wrote:
Hello list, I've been working on this problem for a while and I haven't been able to come up with a solution. I have a couple of functions that plot a bunch of data, then a single point on top of it. What I want is to be able to change the plot of the point without replotting all the data. Consider the following example: x = rnorm(100,1,0.5) y = rnorm(100,1,0.5) plot(x,y,pch=16) points(x[35],y[35],pch=19,col=6,cex=3) What I want to be able to do is to change the purple point to a different value without replotting everything. I know this seems like an odd suggestion, but it comes up a lot with the work I'm doing. I've prepared a package on CRAN called ResearchMethods for a course I'm working on, and there are several functions in there who's GUIs could work better if I could figure this out. If anyone has any ideas, or needs some further explanation, feel free to contact me.
Hi Sam,
An interesting question. Here's a way to erase a point while redrawing
any points within a certain proportion of the plot extent. It wouldn't
be hard to extend this to draw a new point somewhere else if you wanted
it all in one function.
erase.point<-function(x,y,pch=1,col=par("fg"),cex=1,tol=0.02*cex,
erase.index,erase.pch=1,erase.col=par("bg"),erase.cex=1) {
# erase the point
points(x[erase.index],y[erase.index],pch=pch,col=erase.col,cex=1.1*erase.cex)
# repeat the point parameters so that they can be indexed
if(length(pch) < length(x)) pch<-rep(pch,length.out=length(x))
if(length(col) < length(x)) col<-rep(col,length.out=length(x))
if(length(cex) < length(x)) cex<-rep(cex,length.out=length(x))
# work out the x and y differences within which the remaining points
# will be redrawn
xylim<-par("usr")
xtol<-diff(xylim[1:2])*tol
ytol<-diff(xylim[3:4])*tol
for(i in 1:length(x)) {
if(i != erase.index) {
# if this point is within the specified tolerance, redraw it
if(abs(x[i]-x[erase.index]) < xtol && abs(y[i]-y[erase.index]) < ytol)
points(x[i],y[i],pch=pch[i],col=col[i],cex=cex[i])
}
}
}
x = rnorm(100,1,0.5)
y = rnorm(100,1,0.5)
plot(x,y,pch=16)
points(x[35],y[35],pch=19,col=6,cex=3)
erase.point(x,y,pch=19,erase.index=35,erase.pch=19,erase.col="white",erase.cex=3)
Jim
Thanks, I looked into the grid package. The grid package does do a
better job of managing the plotting, but it's still re-plotting the
entire canvas whenever a modifcation is made to a plot.
I guess I should have been a little clearer with my question. Here's
a sample function.
library(tcltk)
x = runif(10000)
y = runif(10000)
v1 <- viewport()
grid.rect(gp = gpar(lty = "dashed"))
pushViewport(plotViewport(c(5.1, 4.1, 4.1, 2.1)))
pushViewport(dataViewport(x, y))
grid.rect()
grid.xaxis()
grid.yaxis()
grid.points(x, y)
grid.text("1:10", x = unit(-3, "lines"), rot = 90)
v2 <- viewport()
push.viewport()
grid.points(x[1],y[1],pch=16,gp=gpar(col='green'),name='pts')
index = tclVar(1)
grid
refresh <- function(...){
i <- as.numeric(tclvalue(index))
grid.edit('pts',x=unit(x[i],'npc'),y=unit(y[i],'npc'))
}
m <- tktoplevel()
pScale <- tkscale(m,from=0,to=10000,orient='horiz',resolution=1,variable=index,command=refresh)
tkgrid(pScale)
The green point should change as the slider is moved, but there are so
many points in the background that replotting them confuses the
graphic. What I want to be able to do is replt the green point
without removing the background.
Sam Stewart
On Wed, Sep 24, 2008 at 11:12 AM, Ben Bolker <bolker at ufl.edu> wrote:
R Help <rhelp.stats <at> gmail.com> writes:
Hello list, I've been working on this problem for a while and I haven't been able to come up with a solution. I have a couple of functions that plot a bunch of data, then a single point on top of it. What I want is to be able to change the plot of the point without replotting all the data. Consider the following example: x = rnorm(100,1,0.5) y = rnorm(100,1,0.5) plot(x,y,pch=16) points(x[35],y[35],pch=19,col=6,cex=3) What I want to be able to do is to change the purple point to a different value without replotting everything.
R's default (base) graphics model is a 'canvas' -- things get drawn, but nothing ever gets erased. (The cheap solution is to overplot in the background color, but that won't work if there's stuff underneath the point that you want to preserve.) You probably need to move to the grid graphics package (hint: buy or borrow Paul Murrell's book) to do something like this. Ben Bolker
______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
R Help wrote:
Thanks, I looked into the grid package. The grid package does do a
better job of managing the plotting, but it's still re-plotting the
entire canvas whenever a modifcation is made to a plot.
I guess I should have been a little clearer with my question. Here's
a sample function.
library(tcltk)
x = runif(10000)
y = runif(10000)
v1 <- viewport()
grid.rect(gp = gpar(lty = "dashed"))
pushViewport(plotViewport(c(5.1, 4.1, 4.1, 2.1)))
pushViewport(dataViewport(x, y))
grid.rect()
grid.xaxis()
grid.yaxis()
grid.points(x, y)
grid.text("1:10", x = unit(-3, "lines"), rot = 90)
v2 <- viewport()
push.viewport()
grid.points(x[1],y[1],pch=16,gp=gpar(col='green'),name='pts')
index = tclVar(1)
grid
refresh <- function(...){
i <- as.numeric(tclvalue(index))
grid.edit('pts',x=unit(x[i],'npc'),y=unit(y[i],'npc'))
}
m <- tktoplevel()
pScale <- tkscale(m,from=0,to=10000,orient='horiz',resolution=1,variable=index,command=refresh)
tkgrid(pScale)
The green point should change as the slider is moved, but there are so
many points in the background that replotting them confuses the
graphic. What I want to be able to do is replt the green point
without removing the background.
Sam Stewart
OK, I see the issue but I don't at the moment see a way around it.
The only R graphics device I know of that actually maintains the full
scene in the way that you want is rgl:
library(rgl)
rgl.bg(color="white")
rgl.points(runif(10000),runif(10000),0,col="black")
rgl.viewpoint(theta=0,phi=0,fov=1)
for (i in 5:995) {
## rgl.points(i/1000,i/1000,0,col="green",alpha=0.5,size=20)
rgl.spheres(i/1000,i/1000,0,col="green",alpha=1,radius=0.02)
rgl.pop()
}
This is kind of an ugly workaround, but maybe it will work for you.
(Really, the fundamental problem is that the plot is ALWAYS being
redrawn -- I think the issue is that rgl just redraws it much faster ...)
I'm curious if anyone else has solutions.
Ben Bolker
R Help wrote:
Thanks, I looked into the grid package. The grid package does do a
better job of managing the plotting, but it's still re-plotting the
entire canvas whenever a modifcation is made to a plot.
I guess I should have been a little clearer with my question. Here's
a sample function.
library(tcltk)
x = runif(10000)
y = runif(10000)
v1 <- viewport()
grid.rect(gp = gpar(lty = "dashed"))
pushViewport(plotViewport(c(5.1, 4.1, 4.1, 2.1)))
pushViewport(dataViewport(x, y))
grid.rect()
grid.xaxis()
grid.yaxis()
grid.points(x, y)
grid.text("1:10", x = unit(-3, "lines"), rot = 90)
v2 <- viewport()
push.viewport()
grid.points(x[1],y[1],pch=16,gp=gpar(col='green'),name='pts')
index = tclVar(1)
grid
refresh <- function(...){
i <- as.numeric(tclvalue(index))
grid.edit('pts',x=unit(x[i],'npc'),y=unit(y[i],'npc'))
}
m <- tktoplevel()
pScale <- tkscale(m,from=0,to=10000,orient='horiz',resolution=1,variable=index,command=refresh)
tkgrid(pScale)
The green point should change as the slider is moved, but there are so
many points in the background that replotting them confuses the
graphic. What I want to be able to do is replt the green point
without removing the background.
The TK canvas is rather good at replotting only what is necessary. Unfortunately, it lacks functionality for a real graphics driver, but you might want to look into demo(tkcanvas).
O__ ---- Peter Dalgaard ?ster Farimagsgade 5, Entr.B c/ /'_ --- Dept. of Biostatistics PO Box 2099, 1014 Cph. K (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk) FAX: (+45) 35327907