I have tried to plot a series of points in R, and I use type="b" as a plot option. However, there is a lot of padding (white space) between the points and the lines between them, so much that the line disappears entirely between some points. Her is a picture of how it looks:
I have tried to make the points smaller with the cex plot option, but this does not help, as it only changes the size of the points and not where the lines between the points between these starts and ends. I do not know if this makes a difference, but the symbols I am using are pch=1.
I am interested in knowing if it is possible to reduce this padding, and how you do so. I am not interested in using type=o as a plot option instead.
Any particular reason why you don't want to use type="o"? It seems like the easiest way to get the effect you want:
# Fake data
set.seed(10)
dfs = data.frame(x=1:10, y=rnorm(10))
plot(y~x,data=dfs, type="o", pch=21, bg='white')
pch=21 is a circle marker like pch=1, but with both border and fill. We set the fill to white with bg="white" to "cover up" the lines that go through the point markers.
You can also use cex to change the marker size to avoid overlap and make the lines between nearby points visible:
set.seed(10)
dfs = data.frame(x=1:100, y=cumsum(rnorm(100)))
plot(y~x,data=dfs, type="o", pch=21, bg="white", cex=0.6)
Using a dataframe named dfs this seems to deliver a mechanism for adjusting the surrounding "white halo" to whatever size of point an halo you want by adjusting the 'cex' values of the white and black points :
plot(y~x,data=dfs, type="l")
with(dfs, points(x,y, pch=16,col="white",cex=1.4))
with(dfs, points(x,y,cex=1) )
I am not an R pro, self-taught- thank you for your help!
I have figured out the following code to my satisfaction, which gives me a 3d plot of my data and I can automatically rotate it. However, I want to stop the automatic redraw of the axes as it spins. I have found many resources using par3d(skipRedraw=TRUE) but I cannot figure out how to incorporate it into my code, it is all a bit beyond me.
Also, (I was going to give up on this one but since I'm asking anyway) I'd also like to be able to have the axes labels stay next to the axis tick marks (rather than across from it/on the other side). But this is secondary.
Thank you in advance!
mydata<-read.csv(file=file.choose(),header=TRUE,row.names=1)
mydata$Colour<-factor(mydata$ColourB,levels=c("Black","Blue","Red","Green","Yellow","Purple","Brown"))
colourb<-as.character(mydata$ColourB)
library(rgl)
open3d()
plot3d(mydata[,"Sr"],
mydata[,"Rb"],
mydata[,"Zr"],
xlab="Sr (ppm)",
ylab="Rb (ppm)",
zlab="Zr (ppm)",
pch=21,
col=colourb,
type="s",
radius=10
)
bgplot3d({
plot.new()
title(main = 'Trace Elements', line = 1)
})
play3d(spin3d(axis=c(0,0,1), rpm=10), duration=10)
It is easy to stop the automatic redraw of the axes. When you use bbox-axes (default), they are redrawn. So you just use fixed position axes. (EDITED: I might misunderstand your quiestion.)
Here is my example (using data trees):
open3d()
plot3d(trees, type="s", radius=0.4, col="red", xlab="xxx", ylab="yyy", zlab="zzz",
axes=F) # not use bbox-axes
axes3d(edges = c("x","y","z")) # draw fixed position axes
box3d() # if you need, draw full box
bgplot3d({
plot.new()
title(main = 'Trees', line = 1)
})
play3d(spin3d(axis=c(0,0,1), rpm=10), duration=10)
# PS: skipRedraw isn't what you think.
plot3d(trees)
par3d(skipRedraw = T) # you can't turn the graph by drag
I have found that when I try to overlay multiple rasters using plot(...,add=T) if I try to overlay more than 3 rasters together the subsequent plot does not align the rasters properly.
My original intent was to create a categorical map of modeled landcover where the darkness of the color representing a cover class varied wrt the certainty in our model projection. To do this, I created a simple script that would loop through each cover class and plot it (e.g., forest, green color on map) using a color gradient from grey (low certainty forest prediction) to full cover color (e.g., dark green for areas are strongly predicted).
What I have found is that using this approach, after the 3rd cover is added to the plot, all subsequent rasters that are overlayed on the plot are arbitrarily misaligned. I have reversed the order of plotting of the cover classes and the same behavior is exhibited meaning it is not an issue with the individual cover class rasters. Even more puzzling in Rstudio, when I use the zoom button to closely inspect the final plot, the misalignment worsens.
Do you have any ideas of why this behavior exists? Most importantly, do you have any suggested solutions or workarounds?
The code and data on the link below has all of the behaviors described captured.
https://dl.dropboxusercontent.com/u/332961/r%20plot%20raster%20add%20issue.zip
Turn plot_gradient=F to see how if you just simply subset a same raster and add the subsets sequentially to the same plot you can replicate the issue. I have already tried setting the extent of the plot device plot(..., ext) but that did not work. I have also checked and the extent of each cover raster is the same.
Below is the figure of the misaligned cover classes. plotting to jpeg device will result in a similar image (i.e., this is not an issue of Rstudio rendering).
Strangely enough, if I zoom into the image using Rstudio, the misalignment is different
For comparison, this is how the covers should align correctly in the landscape
library(raster)
library(colorRamps)
raster_of_classes=raster("C:/r plot raster add issue/raster_of_classes.tif")
raster_of_certainty_of_classes=raster("C:/r plot raster add issue/raster_of_certainty_of_classes.tif")
endCols=c("darkorchid4", "darkorange3", "red3", "green4", "dodgerblue4") #colors to be used in gradients for each class
classes=unique(raster_of_classes)
minVal=cellStats(raster_of_certainty_of_classes, min)
tmp_i=1
addPlot=F
plot_gradient=F #this is for debug only
#classes=rev(classes) #turn this off and on to see how last 2 classes are mis aligned, regardless of plotting order
for (class in classes){
raster_class=raster_of_classes==class #create mask for individual class
raster_class[raster_class==0]=NA #remove 0s from mask so they to do not get plotted
if (plot_gradient){
raster_of_certainty_of_class=raster_of_certainty_of_classes*raster_class #apply class mask to certainty map
}else{
raster_of_certainty_of_class=raster_class #apply class mask to certainty map
}
endCol=endCols[tmp_i] #pick color for gradient
col5 <- colorRampPalette(c('grey50', endCol))
if (plot_gradient){
plot(raster_of_certainty_of_class,
col=col5(n=49), breaks=seq(minVal,1,length.out=50), #as uncertainty values range from 0 to 1 plot them with fixed range
useRaster=T, axes=FALSE, box=FALSE, add=addPlot, legend=F)
}else{
plot(raster_of_certainty_of_class,
col=endCol,
useRaster=T, axes=FALSE, box=FALSE, add=addPlot, legend=F)
}
tmp_i=tmp_i+1
addPlot=T #after plotting first class, all other classes are added
}
I had this problem too and solved it by calling the graphical parameters function, par(), with a subset of parameters, and most importantly, put the new=TRUE in the par() call, not the plot() call, before each additional plot() call. For example:
png(fullname,
width = 3000,
height= 3000)
# original par() call
par(mfrow=c(1,1), cex=3, mar=c(3,3,3,7), bg=bgcol, col=txtcol)
# first plot
plot(zreate,
maxpixels=ncell(zreate),
col=qcol,
colNA=mapbg,
xaxt='n',
yaxt='n',
ext=map_extent,
breaks=tq,
bty='n',
legend=FALSE)
#second plot and par() call
par(mfrow=c(1,1), cex=3, mar=c(3,3,3,7), bg=bgcol, col=txtcol, new=TRUE)
plot(rt,
maxpixels=ncell(rt),
col=dcol,
legend=FALSE,
xaxt='n',
yaxt='n',
ext=map_extent,
bty='n')
#third plot and par() call
par(mfrow=c(1,1), cex=3, mar=c(3,3,3,7), bg=bgcol, col=txtcol, new=TRUE)
plot(r0,
maxpixels=ncell(r0),
col="#9e9ac8",
xaxt='n',
yaxt='n',
ext=map_extent, #PRENAFILTERING fix
bty='n',
legend=FALSE)
In December 2013, I posted a question about exactly this behavior to the R-sig-geo mailing list, and got no useful response (other than a confirmation that it also happens with R versions and OS's different than my own).
Here, for the record, is the reproducible example that I used to illustrate the issue. (See the linked question for some more explanation.)
library(maptools) ## Only needs to be installed for example data
library(raster)
library(rgeos)
## Create an example raster
p <- shapefile(system.file("shapes/co37_d90.shp", package="maptools"))
p <- p[31,] ## A tall narrow county polygon
pr <- gDifference(gBuffer(p, width=.01), p)
r <- rasterize(pr, raster(extent(pr), ncol=100, nrow=100))
## These three are properly registered on one another
plot(r, col="yellow", legend=FALSE)
plot(r, col="green", legend=FALSE, add=TRUE)
plot(r, col="grey", legend=FALSE, add=TRUE)
## All subsequent "layers" are improperly shifted/skewed to right
plot(r, col="yellow", legend=FALSE, add=TRUE)
plot(r, col="blue", legend=FALSE, add=TRUE)
plot(r, col="red", legend=FALSE, add=TRUE)
plot(r, col="grey20", legend=FALSE, add=TRUE)
## Following the above, SpatialPolygons are also shifted/skewed
plot(p, border="red", lwd=2, add=TRUE)
I have run into the same problem and found an answer that is less of a hack than the previous answer. It follows the train of thought described by user "Dial".
The key is to use image(). But add in the argument maxpixels = ncell(x). This way, the resolution is maintained and pixel aggregation does not occur either as much or at all.
> x <- brick(image.path)
> plotRGB(x)
> image(brick.overlay, add = T, col = 'black', maxpixel = ncell(x))
> image(brick.overlay, add = T, col = 'yellow', maxpixel = ncell(x))
The "brick.overlay" would be some mask object, region of interest, or otherwise subsetted data where data is associated with those pixels and all other pixels are NA.
The brick.overlay object should have to have an implied extent based on total number of pixels where all non-interest pixels are NA.
This is hardly the most memory efficient way, but it's the one I know works.
If you use "Dial's" example, I think you would do:
image(r, col="yellow", add=TRUE, maxpixels = ncell(r))
Interesting problem. As you likely know, image() doesn't seem to have the same issue but generally makes uglier maps, right?
library(raster)
library(rgeos)
## Create an example raster
p <- shapefile(system.file("shapes/co37_d90.shp", package="maptools"))
p <- p[31,] ## A tall narrow county polygon
pr <- gDifference(gBuffer(p, width=.01), p)
r <- rasterize(pr, raster(extent(pr), ncol=100, nrow=100))
## These three are properly registered on one another
image(r, col="yellow")
image(r, col="green", add=TRUE)
image(r, col="grey", add=TRUE)
## All subsequent "layers" are also registered
image(r, col="yellow", add=TRUE)
image(r, col="blue", add=TRUE)
image(r, col="red", add=TRUE)
image(r, col="grey20", add=TRUE)
## Following the above, SpatialPolygons are no longer shifted/skewed
plot(p, border="red", lwd=2, add=TRUE)
I have the following problem when displaying a spatial object:
Reproducible example:
x<-c(1:2000)
y<-c(rep(1:20, each=100))
xy <- cbind(x,y)
S <- SpatialPoints(xy)
plot(S)
Which gives the undesired left plot on the panel below. :
However, I would like to reduce the bounding box limits on the y-axis, to show more detail on the y-axis, to achieve a plot similar to the plot on the right panel, but with an sp object. I thought it could be achieved with ylim and xlim. But that doesn't work. I also tried the following based on an example from the sp documentation.
pin<-par("pin")
dxy<-apply(bbox(S), 1, diff)
ratio<-dxy[0]/dxy[2]
par(pin=c(ratio*pin[0.1], pin[1]), xaxs="i", yaxs="i")
plot(S, pch=0.1)
But I don't understand what lines 3 and 4 do and I did try to play around with the values to no avail. Can anyone provide any suggestions please? Thanks.
Just discovered that asp works, so plot(S, asp = 0) solves the problem.
I'm trying to build an histogram using data available from here. I'm using using the CSV version of this database to display the number of exoplantes discovered per year. A simple script would be
bulkdata <- read.csv('file.csv',head=1,sep=',')
pdf(file="yearcount.pdf",family="Times")
bins <- seq(min(bulkdata$discovered,na.rm=T),max(bulkdata$discovered,na.rm=T),by=1)
hist(bulkdata$discovered,breaks=bins,col='gray',ylab="Discovered",xlab="Year",main="",ylim=c(0,100),axes=FALSE)
axis(1, at=seq(1989,2012,by=1))
axis(2, at=seq(0,100,by=10))
grid(nx=10)
hist(bulkdata$discovered,breaks=bins,col='gray',ylab="Discovered",xlab="Year",main="", add=TRUE)
dev.off()
The problem is that the xaxis is not aligned with the 0 point of the yaxis. This is a problem because the lines drawn by grid() does not mean anything because they are not aligned with the ticks! I tried to add in axis(1, at=seq(1989,2012,by=1)) the option line=-1 to correct but this way the axis is correctly drawn but the grid start below the axis. Maybe a non standard package is needed?
?grid says:
If more fine tuning is required, use ‘abline(h = ., v = .)’
directly.
So here's a suggestion:
par(las=1,bty="l")
h <- hist(bulkdata$discovered,breaks=bins,
col='gray',ylab="Discovered",xlab="Year",main="",
ylim=c(0,100),axes=FALSE)
yrs <- 1989:2012
yvals <- seq(0,100,by=10)
axis(1, at=yrs)
axis(2, at=yvals)
abline(h=yvals,v=yrs,col="gray",lty=3)
hist(bulkdata$discovered,breaks=bins,
col='gray',ylab="Discovered",xlab="Year",main="", add=TRUE)
I would consider making the grid lines a little bit sparser (e.g. every 5 years?)