I'm running an R script which plots data over time using plot and some data taken as.Date. I am then adding using grid to add guidelines like so:
plot(as.Date(data[["Date"]]), -data[["dbns"]], lwd=1, col = colours[i], type="l",ylim=ylimit, xlim=xlimit, xlab="", ylab =ylabel)
grid(NULL,NULL,lwd=1)
Below is an example of how this comes out (actually example is after this plot is looped over 3 times to add each line)
The problem I am having is that the guidelines added with grid do not line up with the default tick marks added by plot. The plot function by default adds tick every 10 years, which is what I want. Looking at axTicks(1) gives me 0 5000 10000 15000 which is the locations of guidelines in units of days after 1/1/1970.
Is there a way to find out the location of the tickmarks that have been added? And more importantly, is there then a way to set the guidelines to match these locations?
I realise that for this example the ticks are [0, 365.25*10, 365.25*20 etc.] but an answer which solves a general case would be nice.
Thanks
JP
EDIT:
Here is a reproducible example to show exactly what I mean.
data <- read.csv("test.csv"), header =TRUE)
data[["Date"]] <- as.Date(data[["Date"]], format = "%d/%m/%Y")
data<-data[order(as.Date(data$Date)),]
plot(as.Date(data[["Date"]]), -data[["dbns"]], type="l", xlim=xlimit)
grid(NULL,NULL,lwd=3)
Where the file test.csv looks like this (extract of actual data)
bore Date dbns
42230210A 20/01/2009 13.13
42230210A 8/05/2009 13.21
42230210A 18/06/2009 13.19
42230210A 3/08/2009 13.2
42230210A 2/09/2009 13.25
42230210A 1/10/2009 13.3
42230210A 3/12/2009 13.32
42230210A 24/02/2010 13.3
42230210A 18/05/2010 13.3
42230210A 25/04/2012 11.45
42230210A 27/09/1966 11.18
42230210A 28/10/1969 11.14
42230210A 6/01/1970 11.03
42230210A 5/06/1973 10.68
42230210A 28/08/1973 10.63
42230210A 2/10/1973 10.73
42230210A 4/12/1973 10.7
42230210A 20/02/1980 11.39
42230210A 29/04/1980 11.45
42230210A 27/08/1980 11.45
42230210A 22/06/1988 11.14
42230210A 27/02/1996 11.78
42230210A 6/08/1996 11.68
42230210A 8/02/2000 11.64
42230210A 8/06/2000 11.71
42230210A 7/09/2000 11.75
42230210A 15/07/2008 13.01
The output of which is below. The guidelines are offset from the tick marks?
So checking ?grid suggests that what's going on is that it is placing the grid lines based on the "default" tick mark locations, but since you plotted a date object, R didn't use the "default" (in the sense of treating the date as a numeric variable) to place the tick marks.
The documentation further notes that if you need finer control, you should use abline to place them directly.
So you probably want to do this:
plot(as.Date(data[["Date"]]), -data[["dbns"]], type="l")
grid(NA,NULL,lwd=3)
v <- as.numeric(as.Date(paste0(c(1970,1980,1990,2000,2010),'-01-01')))
abline(v = v,lty = "dotted",col = "lightgray",lwd = 3)
There is a function Axis.Date which creates appropriately pretty axis tick locations for an axis for a Date object. This does not change par('xaxp') which grid uses to find the locations of the tick marks.
We can get around by creating the axis manually (and saving the values)
# assuming your data is called DD
DD$Date <- as.Date(as.character(DD$Date), format = '%d/%m/%Y')
# don't plot the x axis (xaxt = 'n')
plot(-dbns~Date,data = DD[order(DD$Date),], type="l", xaxt = 'n')
# create the axis and save the tick locations
at <- as.numeric(Axis(side = 1, x = DD$Date))
grid(NA,NULL,lwd=3)
abline(v = at,lty = "dotted",col = "lightgray",lwd = 3)
The answer to your questions are the following ones:
Is there a way to find out the location of the tickmarks that have been added?
Just after the plot function call, use the function axis.Date
x_ticks <- axis.Date(1, data$Date, labels = FALSE)
Variable x_ticks contains the location of the ticks used in the x axis (identified by 1 in the first parameter of the function).
And more importantly, is there then a way to set the guidelines to match these locations?
grid(NA, NULL, lwd=3)
x_ticks <- axis.Date(1, data$Date, labels = FALSE)
abline(v = x_ticks, lty = 3, col ="lightgray", lwd = 3)
With the NA in the first parameter of the grid function (nx = NA), you avoid that the vertical guidelines are printed in the wrong places. The second gives you the location of the ticks. Finally, the third prints the guidelines in the right locations.
In this way, the plot you obtain looks like, I guess, the one you expected
Related
I am trying to use spplot to visualize plots from different months. I'd like to change this figure so the same months are in the same columns to easily compare. I would like to push May 2016 5 panels in, so all the rest of the months are in line. I hope this makes sense.
click here for figure
I have missing data for Dec2017 for now which is why it's blacked out.
Here is my code:
stack_months <- stack(May2016, June2016, July2016, Aug2016, Sep2016, Oct2016, Nov2016, Dec2016, January2017, Febuary2017, March2017, April2017, May2017, June2017, July2017, July2017, Aug2017, Sep2017, Oct2017, Nov2017, Dec2017, January2018, Febuary2018, March2017, April2018, May2018, June2017, July2017, July2018, Aug2018, Sep2018, Oct2018, Nov2018, Dec2018, January2019, Febuary2019, March2019, April2019, May2019, June2019, July2019, July2019)
spplot(stack_months, col.regions=viridis(20), names.attr = c("May2016", "June2016", "July2016", "Aug2016", "Sep2016", "Oct2016", "Nov2016", "Dec2016",
"Jan2017", "Feb2017", "March2017", "April2017", "May2017", "June2017", "July2017", "July2017", "Aug2017", "Sep2017", "Oct2017", "Nov2017", "Dec2017",
"Jan2018", "Feb2018", "March2017", "April2018", "May2018", "June2017", "July2017", "July2018", "Aug2018", "Sep2018", "Oct2018", "Nov2018", "Dec2018",
"Jan2019", "Feb2019", "March2019", "April2019", "May2019", "June2019", "July2019", "July2019"), layout = c(12,4))
Is there an easy way to manipulate the panels?
Note that you have type some of the months twice, for example July2017 appeared 3 times and March2017, 2 times, June2017 2x and July2019 2x.
What I have below are complete months from May2016 to July2019, so that when you plot, the months will align.
library(raster)
library(sp)
library(viridis)
library(lattice)
months=c("May2016", "June2016", "July2016", "Aug2016", "Sep2016", "Oct2016",
"Nov2016", "Dec2016", "Jan2017", "Feb2017", "March2017", "April2017",
"May2017", "June2017", "July2017","Aug2017", "Sep2017",
"Oct2017", "Nov2017", "Dec2017","Jan2018", "Feb2018", "March2018",
"April2018", "May2018", "Jun2018", "July2018", "Aug2018",
"Sep2018", "Oct2018", "Nov2018", "Dec2018","Jan2019", "Feb2019",
"March2019", "April2019", "May2019", "June2019", "July2019")
I don't have your data, so I simulate something for the image:
r <- raster(system.file("external/test.grd", package="raster"))
stack_months = do.call(stack,lapply(months,function(i)runif(1)*r))
You defined layout to be 12,4 so you will have 48 entries which are filled by row. In your case, the first 4 will not be plotted and the last 5 will not be plotted:
SKIP = rep(FALSE,12*4)
SKIP[1:4] = TRUE
SKIP[44:48] = TRUE
Then we plot using the SKIP above:
spplot(stack_months, col.regions=viridis(20),
layout = c(12,4),
strip = strip.custom(par.strip.text = list(cex = 0.65)),
names.attr = months,
skip=SKIP
)
I done four raster plots which were 2 layered and I done pretty simple using par(mfrow=c(2,2)), but when setting a common legend makes the plot a mess, It always overlap with other plots. I tried change some parameter values but still the issue persists. this is my code.
library(maps)
library(raster)
# set colour
col<- colorRampPalette(c("grey","green","green3","darkgreen"))
#set panel for four plots
par(mfrow=c(2,2),mar=c(2,2,2,2),oma=c(0,0,0,0))
#plot1
plot(novchl,col=col(20),legend =FALSE)
contour(novsst,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot2
plot(decchl,col=col(20),legend =FALSE)
contour(decsst,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot3
plot(janchl,col=col(20),legend =FALSE)
contour(jansst,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot4
plot(febchl,col=col(20),legend =FALSE)
contour(febsst,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
reset para to single plot
par(mfrow=c(1,1),new=FALSE,mar=c(0,0,0,8))
plot(novchl,legend.only=TRUE ,legend.shrink=1, legend.width=1, zlim=c(0, 1),
axis.args=list(at=pretty(0:1), labels=pretty(0:1)),col=col(20),
legend.args=list(text='Whatever',"bottom", font=2, line=2.3))
and I got image like this.plz help, thanks in advance
I'm just adressing the overlapping-topic of your question without considering any other changes in the layout (and not adressing the warning messages). To get a MWE, I use the test-grid data from the raster package.
I think you were almost there (mark the oma arguments in the calls to par)...
Set the 4th entry in your oma argument in your first call to par to something higher than 0 in order to leave some space on the right side. Then, when resetting the parameters to a single plot, also reset this value to e.g. 0 to place the legend on the empty space. Something like this
library(maps)
library(raster)
r <- raster(system.file("external/test.grd", package="raster"))
# set colour
col<- colorRampPalette(c("grey","green","green3","darkgreen"))
#set panel for four plots
par(mfrow=c(2,2),mar=c(2,2,2,2),oma=c(0,0,0,4))
#plot1
plot(r,col=col(20),legend =FALSE)
contour(r,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot2
plot(r,col=col(20),legend =FALSE)
contour(r,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot3
plot(r,col=col(20),legend =FALSE)
contour(r,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#plot4
plot(r,col=col(20),legend =FALSE)
contour(r,maxpixels = 999,add=TRUE)
map(xlim=c(85, 93),ylim=c(2, 16 ),asp=1,add=TRUE,fill=TRUE,col="grey")
#reset para to single plot
par(mfrow=c(1,1),new=FALSE, oma=c(0,0,0,0))
plot(r,legend.only=TRUE ,legend.shrink=1, legend.width=1, zlim=c(0, 1),
axis.args=list(at=pretty(0:1), labels=pretty(0:1)),col=col(20),
legend.args=list(text='Whatever',"bottom", font=2, line=2.3))
I cannot seem to move the legend from the bottom of my graph when using timePlot from R openair. Can anyone assist?
Here is my script and some data:
library(openair)
timeozone <- import(npsfiles[2], date="year", date.format = "%Y", header=TRUE, na.strings="NA")
timePlot(timeozone, pollutant = c("BIBEKB", "MACAGO", "MACAHM", "VOYASB"), group = TRUE, ylab = "Ozone (ppbv)", key.columns = 1)
Data:
Year BIBEKB
1990 70.25
1991 59.25
1992 62.5
1993 64.25
1994 76
1995 68.25
1996 78.375
1997 66.25
I have tried:
auto.key = list(space = "right")
space = "right"
key.position = "right"
I have also tried putting the legend specification outside the timePlot line of code, but I am hoping to be able to get it to work with the location specification in the timePlot function. Thanks for any help you can provide:
plot.new()
legend(1, -1, c("BIBEKB","MACAGO","MACAHM", "VOYASB"))
I saw that "key.position =" function option was added in github repo of openair timePlot
But it's developer version. So you can try and install it manually. May be it'll help you!
How to install from Github repository
I have a file called rRna_RDP_taxonomy_phylum with the following data :
364 "Firmicutes" 39.31
244 "Proteobacteria" 26.35
218 "Actinobacteria" 23.54
65 "Bacteroidetes" 7.02
22 "Fusobacteria" 2.38
6 "Thermotogae" 0.65
3 unclassified_Bacteria 0.32
2 "Spirochaetes" 0.22
1 "Tenericutes" 0.11
1 Cyanobacteria 0.11
And I'm using this code for creating a pie chart in R:
if(file.exists("rRna_RDP_taxonomy_phylum")){
family <- read.table ("rRna_RDP_taxonomy_phylum", sep="\t")
piedat <- rbind(family[1:7, ],
as.data.frame(t(c(sum(family[8:nrow(family),1]),
"Others",
sum(family[8:nrow(family),3])))))
png(file="../graph/RDP_phylum_low.png", width=600, height=550, res=75)
pie(as.numeric(piedat$V3), labels=piedat$V3, clockwise=TRUE, col=graph_col, main="More representative Phyliums")
legend("topright", legend=piedat$V2, cex=0.8, fill=graph_col)
dev.off()
png(file="../graph/RDP_phylm_high.png", width=1300, height=850, res=75)
pie(as.numeric(piedat$V3), labels=piedat$V3, clockwise=TRUE, col=graph_col, main="More representative Phyliums")
legend("topright", legend=piedat$V2, cex=0.8, fill=graph_col)
dev.off()
}
I've been using this code for different datafiles and it works fine, but with the file presented adobe it crash returning the following message:
Error in Summary.factor(c(6L, 2L, 1L), na.rm = FALSE) :
sum not meaningful for factors
Calls: rbind -> as.data.frame -> t -> Summary.factor
Execution halted
I need to understand why it crash with this file and if there's any way to prevent this kind of errors.
Thanks!
The error comes when you try to call sum(x) and x is a factor.
What that means is that one of your columns, though they look like numbers are actually factors (what you are seeing is the text representation)
simple fix, convert to numeric. However, it needs an intermeidate step of converting to character first. Use the following:
family[, 1] <- as.numeric(as.character( family[, 1] ))
family[, 3] <- as.numeric(as.character( family[, 3] ))
For a detailed explanation of why the intermediate as.character step is needed, take a look at this question: How to convert a factor to integer\numeric without loss of information?
I've been mapping a choropleth map and when I compare the colours drawn to the numbers they re assigned to it doesn't fit.
so here is my data
zip latitude longitude count2.x count2.freq reg colorBuckets colma
99501 61.21680 -149.87828 AK 67 Alaska 1 #EDF8FB
35010 32.90343 -85.92669 AL 1582 Alabama 3 #99D8C9
90001 33.97291 -118.24878 CA 20970 California 6 #006D2C
20001 38.90771 -77.01732 DC 952 NA 2 #CCECE6
so the code from the beginning that I've been using is the following
library("zipcode")
library("maps")
library("plyr")
library("RColorBrewer")
colors=brewer.pal(6, "BuGn")
data(zipcode)
merge1<-merge(zipcode, tel2, by.x='zip', by.y='zip_code', all.y=TRUE)
result<- ddply(merge1, .(state), transform, count2 = count(state))
#remove NA's#
final<- result[complete.cases(result),]
#remove duplicates#
nodupl <- final[!duplicated(final$state),]
#add state to abbreviations#
nodupl$reg<-state.name[match(nodupl$count2.x, state.abb)]
#intervalle bestimmen#
nodupl$colorBuckets<- as.numeric(cut(nodupl$count2.freq, c(0,500,1000,5000,10000,15000,22000)))
#intervall legend#
text<- c("< 500", "500 - 999", "1000 - 4999","5000 - 9999", "10000 - 14999", "15000 - 22000")
#see what color is assign to where#
nodupl$colma<- colors[nodupl$colorBuckets]
map("state",regions=nodupl$reg, exact=FALSE, col = colors[nodupl$colorBuckets], fill = TRUE,resolution = 0,lty = 0)
map("state",col = "black",fill=FALSE,add=TRUE,lty=1,lwd=1)
#legend plotten#
par(xpd=TRUE)
legend("bottomleft", text, horiz=FALSE, fill=colors)
so the problem is again if I see the legend the colours are assigned right but if I double check the numbers in my column (row count2.freq) with the colours on the map they don't fit. e.g california is really light colored but it should be dark. does anyone see what has been done wrong. plus I have some trouble with positioning the legend the way I have it is right on the map so Idon't see the map anymore. what could I do about that?
thanks for your help even though its saturday
The region Alaska is not available in the map function. Hence, your map shows the second and third entry of nodupl$reg (i.e., Alabama and California). But the first and second of your colours are used.
To print these states in the desired colours, use the command
map("state", regions=nodupl$reg[2:3], exact=FALSE,
col = colors[nodupl$colorBuckets][2:3], fill = TRUE,resolution = 0,lty = 0)
But I recommend searching a map of Alaska too.