Write using mouse on R plot? - r

I created scattergram using the plot() function in R.
Is there any possibility to draw on this graph?
I would like to add a straight line and get parameters of it, but in my opinion abline() can be inconvenient (I would like to draw many lines and choose one which will be most proper).
How can I accomplish this task?

Take a look at RStudio and this example:
library(manipulate)
data = matrix(rnorm(20), ncol = 2)
example <- function(data, a, b){
plot(data[,1],data[,2])
abline(a = a, b = b)
}
manipulate(
example(data, a, b),
a = slider(-5,5),
b = slider(-5,5)
)
This will put a new line on the plot, and allow you to tweak its slope and intercept.
This was inspired by the example on this page: http://support.rstudio.org/help/discussions/questions/106-rstudio-manipulate-command
Note that this requires installing RStudio (it ships with the manipulate package, I believe). For more info, see the site.
Others' solutions with locator can be done in base R.

Use locator(), a function that allows you to get the coordinates of the mouse pointer when clicking on a plot. Then use
plot(cars)
xy <- locator(n=2)
lines(xy, col="red", lwd=5)
lm(y~x, xy)
abline(coef(lm(y~x, xy)))
coef(lm(y~x, xy))
(Intercept) x
33.142094 1.529687
Of course the correct way of fitting lines through data is to use a proper model. Here is how you can do it with lm:
abline(coef(lm(dist~speed, cars)), col="blue")
I made the following graph with this code:
The thick red line is the line connecting my two mouse clicks
The black line is the abline through these points
The blue line is the line of best fit produced by lm
Warning 1: locator only works on some graphics devices. See ?locator for more details.
Warning 2: Drawing lines of fit by hand could well be a really stupid idea. Use a regression function like lm or a smoothing function like loess instead.

If you were hoping to add horizontal or vertical lines to your plot interactively, you may want to use the locator() function to capture the position of a mouse click on the plot.
For example, the following code would allow the repeated addition of vertical lines to an existing plot:
repeat {
click.loc <- locator(1)
if(!is.null(click.loc)) abline(v=click.loc$x)
else break
}
You could adapt this for horizontal lines with abline(h=click.loc$y)

Related

R, suppress plot from curve function

when using the "curve" function in R, how do you suppress/stop the plot from showing up? For example, this code always plots the curve
my_curve = curve(x)
Is there a parameter to do this or should I being using a different function? I just want the x y points as a dataframe from the curve.
curve() is from the graphics library and is unhandy for generating lists.
Just try using:
x = seq(from, to, length.out = n)
y = function(x)
If you stick to the curve function, the closest to a solution I know is adding dev.off() after the curve() statement!
Here's a way to take advantage of the part of curve that you want without generating a plot.
I made a copy of the curve function (just type curve in the console); called it by a new name (curve2); and commented out the four lines at the end starting with if (isTRUE(add)). When it's called and assigned, I had a list with two vectors—x and y. No plot.

Simulate minefields with two samples in the same plot in R

I am trying to simulate a minefield by plotting two Poisson distributed samples in the same plot, one with a higher intensity and smaller area than the other. This is the minefield and the other is just noise (stones, holes, metal) seen as points. I cannot get R to plot the points with the same units in the axis. Whatever I do, the points span the entire plot, even though I only want the X points to cover a quarter of the plot. My R-code is just the following:
library(spatstat)
Y = rpoispp(c(5),win=owin(c(0,10),c(0,10)))
X = rpoispp(c(10),win=owin(c(0,5),c(0,5)))
Please let me know if you can help me.
My guess is that you are doing something like:
> plot(Y)
> plot(X)
to plot the points.
The problem with this is that the default behavior of the plot function for the class ppp (which is what the rpoispp function returns) is to create a new plot with just its points. So the second plot call essentially erases the first plot, and plots its own points in a differently scaled window. You can override this behavior by setting the option add=TRUE for the second plot. So the code
> plot(Y)
> plot(X, add=TRUE, cols="red")
should get you something like:
Check out the docs (help(plot.ppp)) for more explanation and other options to prettify the plot.

Save the orientation of a RGL plot3d() plot

I have a 3D plot using RGL. I would like to make identical plots using color to highlight the distribution of some variable. To do this I would like to have identical plots, how do I find and set the orientation of a plot?
Once I make a preliminary plot, I move it around to find a nice display angle and I would like to save that angle and incorporate it into future plotting scripts. Anyone have a suggestion on how to do this?
library(rgl)
plot3d(iris)
#play with the plot to find a good angle
#save the angle for future plots
Ben's comment basically answers your question; this just applies expand.dots to what he wrote ;)
## In an inital session:
library(rgl)
plot3d(iris)
## Now move the image around to an orientation you like
## Save RGL parameters to a list object
pp <- par3d(no.readonly=TRUE)
## Save the list to a text file
dput(pp, file="irisView.R", control = "all")
.......
## Then, in a later session, to recreate the plot just as you had it:
library(rgl)
pp <- dget("irisView.R")
plot3d(iris)
par3d(pp)

How can I recreate this 2d surface + contour + glyph plot in R?

I've run a 2d simulation in some modelling software from which i've got an export of x,y point locations with a set of 6 attributes. I wish to recreate a figure that combines the data, like this:
The ellipses and the background are shaded according to attribute 1 (and the borders of these are of course representing the model geometry, but I don't think I can replicate that), the isolines are contours of attribute 2, and the arrow glyphs are from attributes 3 (x magnitude) and 4 (y magnitude).
The x,y points are centres of the triangulated mesh I think, and look like this:
I want to know how I can recreate a plot like this with R. To start with I have irregularly-spaced data due to it being exported from an irregular mesh. That's immediately where I get stuck with R, having only ever used it for producing box-and-whisper plots and the like.
Here's the data:
https://dl.dropbox.com/u/22417033/Ellipses_noheader.txt
Edit: fields: x, y, heat flux (x), heat flux (y), thermal conductivity, Temperature, gradT (x), gradT (y).
names(Ellipses) <- c('x','y','dfluxx','dfluxy','kxx','Temps','gradTx','gradTy')
It's quite easy to make the lower plot (making the assumption that there is a dataframe named 'edat' read in with:
edat <- read.table(file=file.choose())
with(edat, plot(V1,V2), cex=0.2)
Things get a bit more beautiful with:
with(edat, plot(V1,V2, cex=0.2, col=V5))
So I do not think your original is being faithfully represented by the data. The contour lines are NOT straight across the "conductors". I call them "conductors" because this looks somewhat like iso-potential lines in electrostatics. I'm adding some text here to serve as a search handle for others who might be searching for plotting problems in real world physics: vector-field (the arrows) , heat equations, gradient, potential lines.
You can then overlay the vector field with:
with(edat, arrows(V1,V2, V1-20*V6*V7, V2-20*V6*V8, length=0.04, col="orange") )
You could"zoom in" with xlim and ylim:
with(edat, plot(V1,V2, cex=0.3, col=V5, xlim=c(0, 10000), ylim=c(-8000, -2000) ))
with(edat, arrows(V1,V2, V1-20*V6*V7, V2-20*V6*V8, length=0.04, col="orange") )
Guessing that the contour requested if for the Temps variable. Take your pick of contourplots.
require(akima)
intflow<- with(edat, interp(x=x, y=y, z=Temps, xo=seq(min(x), max(x), length = 410),
yo=seq(min(y), max(y), length = 410), duplicate="mean", linear=FALSE) )
require(lattice)
contourplot(intflow$z)
filled.contour(intflow)
with( intflow, contour(x=x, y=y, z=z) )
The last one will mix with the other plotting examples since those were using base plotting functions. You may need to switch to points instead of plot.
There are several parts to your plot so you will probably need several tools to make the different parts.
The background and ellipses can be created with polygon (once you figure where they should be).
The contourLines function can calculate the contour lines for you which you can add with the lines function (or contour has and add argument and could probably be used to add the lines directly).
The akima package has a function interp which can estimate values on a grid given the values ungridded.
The my.symbols function along with ms.arrows, both from the TeachingDemos package, can be used to draw the vector field.
#DWin is right to say that your graph don't represent faithfully your data, so I would advice to follow his answer. However here is how to reproduce (the closest I could) your graph:
Ellipses <- read.table(file.choose())
names(Ellipses) <- c('x','y','dfluxx','dfluxy','kxx','Temps','gradTx','gradTy')
require(splancs)
require(akima)
First preparing the data:
#First the background layer (the 'kxx' layer):
# Here the regular grid on which we're gonna do the interpolation
E.grid <- with(Ellipses,
expand.grid(seq(min(x),max(x),length=200),
seq(min(y),max(y),length=200)))
names(E.grid) <- c("x","y") # Without this step, function inout throws an error
E.grid$Value <- rep(0,nrow(E.grid))
#Split the dataset according to unique values of kxx
E.k <- split(Ellipses,Ellipses$kxx)
# Find the convex hull delimiting each of those values domain
E.k.ch <- lapply(E.k,function(X){X[chull(X$x,X$y),]})
for(i in unique(Ellipses$kxx)){ # Pick the value for each coordinate in our regular grid
E.grid$Value[inout(E.grid[,1:2],E.k.ch[names(E.k.ch)==i][[1]],bound=TRUE)]<-i
}
# Then the regular grid for the second layer (Temp)
T.grid <- with(Ellipses,
interp(x,y,Temps, xo=seq(min(x),max(x),length=200),
yo=seq(min(y),max(y),length=200),
duplicate="mean", linear=FALSE))
# The regular grids for the arrow layer (gradT)
dx <- with(Ellipses,
interp(x,y,gradTx,xo=seq(min(x),max(x),length=15),
yo=seq(min(y),max(y),length=10),
duplicate="mean", linear=FALSE))
dy <- with(Ellipses,
interp(x,y,gradTy,xo=seq(min(x),max(x),length=15),
yo=seq(min(y),max(y),length=10),
duplicate="mean", linear=FALSE))
T.grid2 <- with(Ellipses,
interp(x,y,Temps, xo=seq(min(x),max(x),length=15),
yo=seq(min(y),max(y),length=10),
duplicate="mean", linear=FALSE))
gradTgrid<-expand.grid(dx$x,dx$y)
And then the plotting:
palette(grey(seq(0.5,0.9,length=5)))
par(mar=rep(0,4))
plot(E.grid$x, E.grid$y, col=E.grid$Value,
axes=F, xaxs="i", yaxs="i", pch=19)
contour(T.grid, add=TRUE, col=colorRampPalette(c("blue","red"))(15), drawlabels=FALSE)
arrows(gradTgrid[,1], gradTgrid[,2], # Here I multiply the values so you can see them
gradTgrid[,1]-dx$z*40*T.grid2$z, gradTgrid[,2]-dy$z*40*T.grid2$z,
col="yellow", length=0.05)
To understand in details how this code works, I advise you to read the following help pages: ?inout, ?chull, ?interp, ?expand.grid and ?contour.

Circling a particular box in R boxplot

Is it possible to circle a particular box in a boxplot in R? The assumption here is that I know beforehand which of the boxes it is that I have to highlight.
I heartily second #csgillespie's suggestion to just make it a different color.
That said, I played around a bit, and this is what I came up with (using #Marc's data):
df <- data.frame(s1=rnorm(100), s2=rnorm(100, mean=2), s3=rnorm(100, mean=-2))
Plot the boxplot and keep the stats for plotting the ellipse:
foo <- boxplot(df, border=c(8,8,1), lwd=c(1,1,3))
Set semimajor and semiminor axes:
aa <- 0.5
bb <- foo$stats[4,3]-foo$stats[2,3]
Plot a parameterized ellipse around the third box:
tt <- seq(0,2*pi,by=.01)
lines(3+aa*cos(tt),foo$stats[3,3]+bb*sin(tt))
If you want to go with a somewhat hand drawn look and can do some interactive parts (for example, creating a presentation where one slide just shows the plot, then the next slide includes the circling of the one of interest).
use the locator function to click on points that surround the part of the plot that is of interest, you might want to set type='l' so you can see the shape that you are making (but then will need to recreate the plot without the added lines)
pass the return value from above to the xspline function with other options.
example:
boxplot(count ~ spray, data = InsectSprays, col = "lightgray")
tmp <- locator(type='l') # click on plot around box of interest
boxplot(count ~ spray, data = InsectSprays, col = "lightgray")
xspline(tmp, open=FALSE, border='red', lwd=3)

Resources