Domanda

I have plotted three time series graphs on three separate screens. All works fine apart from the x-axis will not plot what I'm asking it to.

I have used the code from this Stack Overflow question, which worked for one screen, i.e. all three graphs on one screen, but it refuses to register on the three screen format with no error messages.

dev.new()
plot(tp,screens=c(1,2,3),col=c("deepskyblue","seagreen3","orchid4"),ylim=c(0,1600),lwd="3",ylab=(expression("TP"~~(mu*"g/L"))),xlab=NA,
main="Seasonal variation of total phosphorus in Water Friendly Farming catchments",cex.main=2,xaxt="n")
legend(locator(1),legend=c("Barkby Brook","Eye Brook","Stonton Brook"),fill=c("deepskyblue","seagreen3","orchid4"),bty="n")
times<-time(tp)
ticks<-seq(times[1],times[length(times)],by=90)
axis(1,at=ticks,labels=c("Spring 2012","Summer 2012","Autumn 2012","Winter 2012","Spring 2013","Summer 2013","Autumn 2013","Winter 2013","Spring 2014"))

TP stands for total phosphorus at three sites, I have merged three zoo objects to obtain it. I then merged the zoo object to a separate zero width zoo object which contains dates from 2012-03-26 to 2014-04-13.

DATA:

mydata<-structure(list(date = structure(c(16054, 15783, 16139, 15528, 
15615, 15726, 15957, 16155, 15922, 16013, 16105, 15594, 15687, 
16012, 15614, 15684, 16041, 15533, 15841, 16055, 16064, 15916, 
15522, 15621, 16065, 15759, 15868, 16156, 15830, 15629), class = "Date"), 
month = structure(c(7L, 17L, 18L, 12L, 22L, 10L, 25L, 18L, 
5L, 21L, 9L, 24L, 6L, 21L, 22L, 6L, 7L, 12L, 19L, 7L, 7L, 
13L, 12L, 22L, 7L, 8L, 15L, 18L, 19L, 22L), .Label = c("April.2012", 
"April.2013", "April.2014", "Aug.2012", "Aug.2013", "Dec.2012", 
"Dec.2013", "Feb.2013", "Feb.2014", "Jan.2013", "Jan.2014", 
"July.2012", "July.2013", "June.2012", "June.2013", "March.2012", 
"March.2013", "March.2014", "May.2013", "Nov.2012", "Nov.2013", 
"Oct.2012", "Oct.2013", "Sept.2012", "Sept.2013"), class = "factor"), 
year = c(2013L, 2013L, 2014L, 2012L, 2012L, 2013L, 2013L, 
2014L, 2013L, 2013L, 2014L, 2012L, 2012L, 2013L, 2012L, 2012L, 
2013L, 2012L, 2013L, 2013L, 2013L, 2013L, 2012L, 2012L, 2013L, 
2013L, 2013L, 2014L, 2013L, 2012L), tp.barkby = c(200.74, 
103.32, 65.6, NA, 94.37, NA, 1110.46, 105.87, NA, 63.68, 
87, 266.29, NA, 114.62, 184.21, 87.95, 148.81, NA, NA, 204.81, 
138.38, 298.48, 120.8, 146.8, 96.6, 91.16, 384.18, 94.16, 
141.72, 125), tp.eyebrook = c(117.59, 101.74, 102.35, 180, 
131.74, NA, 232.5, 144.82, 487.23, 105.26, 95.75, 250.1, 
NA, 99.93, 144.37, 87.95, 107.14, NA, 105.41, 489.33, 147.91, 
132.52, 105.6, 108.8, 111, 76.95, 193, 130.74, 113.17, 134
), tp.stonton = c(85.2, 99.9, 94.85, NA, 54.9, 79.68, 168.86, 
170.08, 284.05, 133.95, 80.5, 102, NA, NA, 61.21, NA, 68.1, 
NA, 107.23, 367.19, 152.91, 131.33, 79.2, 67.8, 88.26, 56.16, 
151.68, 161.79, 61.5, 272)), .Names = c("date", "month",
"year", "tp.barkby", "tp.eyebrook", "tp.stonton"), row.names = c(582L, 
 311L, 667L, 56L, 143L, 254L, 485L, 683L, 450L, 541L, 633L, 122L, 
215L, 540L, 142L, 212L, 569L, 61L, 369L, 583L, 592L, 444L, 50L, 
149L, 593L, 287L, 396L, 684L, 358L, 157L), class = "data.frame")

mydata$date<-as.Date(mydata$date)
attach(mydata)
str(mydata)
library(zoo)
#Total Phosphorus
#1 - create a zero-width (dataless) zoo object with the missing dates/times.
dates<-seq(from=as.Date("2012-03-26"), to=as.Date("2014-04-13"), by=1)
empty<-zoo(,dates)
#2 - create zoo objects from the data
ts.tpb<-zoo(tp.barkby,date)
ts.tpe<-zoo(tp.eyebrook,date)
ts.tps<-zoo(tp.stonton,date)
#3 - merge the zoo objects and apply na.approx
merged.tp<-na.approx(merge(ts.tpb,ts.tpe,ts.tps))
#4 - merge the dataless with the datafull 
tp<-na.approx(merge(merged.tp,empty,all=TRUE))
#Three screen plot
dev.new()
plot(tp,screens=c(1,2,3),col=c("deepskyblue","seagreen3","orchid4"),ylim=c(0,1600),lwd="3",    ylab=(expression("TP"~~(mu*"g/L"))),xlab=NA,
main="Seasonal variation of total phosphorus in Water Friendly Farming     
catchments",cex.main=2,xaxt="n")
legend(locator(1),legend=c("Barkby Brook","Eye Brook","Stonton             
Brook"),fill=c("deepskyblue","seagreen3","orchid4"),bty="n")
times<-time(tp)
ticks<-seq(times[1],times[length(times)],by=90)
axis(1,at=ticks,labels=c("Spring 2012","Summer 2012","Autumn 2012","Winter     2012","Spring 2013","Summer 2013","Autumn 2013","Winter 2013","Spring 2014"))
#Axis at and labels will differ as this is not the whole dataset

I hope that helps.......

È stato utile?

Soluzione 2

Unfortunately the default plot.zoo function internally changes par settings when you plot multiple plots and then automatically resets them when the function exists. When it resets the par parameters, this resets the plotting surface so subsequent calls to axis do not work. This function does not do this when only drawing a single time series.

There is no super easy/robust way to fix this. But, if you are feeling bold, you can perform a surgery on the function and insert new code in there. (This is not a generally recommended practice, but in this case it will make your life easier). I did this with zoo version 1.7-10. To make sure this will work for you, check that

body(plot.zoo)[19:20]

returns

do.call("title", title.args)(return(invisible(x)))

because we are going to add a line of code between those two statements. We will do that with

plot.zoo2<-plot.zoo
bl<-as.list(body(plot.zoo2))
bl<-c(
    bl[1:19], 
    quote(axis(1,at=ticks,labels=tick.lables)), 
    bl[20]
)
body(plot.zoo2)<-as.call(bl)

We've actually created a new function called plot.zoo2 that adds in a call to axis with our desired values. Now we call almost the same way we would the normal plotting function, but we just use our new version instead.

#define these before the plot() since we use them in our function now
times<-time(tp)
ticks<-seq(times[1],times[length(times)],by=90)
tick.labels<-c("Spring 2012","Summer 2012","Autumn 2012","Winter     2012","Spring 2013","Summer 2013","Autumn 2013","Winter 2013")

plot.zoo2(tp,screens=c(1,2,3),
    col=c("deepskyblue","seagreen3","orchid4"),
    ylim=c(0,1600),lwd="3",
    ylab=(expression("TP"~~(mu*"g/L"))),xlab=NA,xaxt="n",
    main="Seasonal variation of total phosphorus",
    cex.main=2)

Which gives

sample result

Altri suggerimenti

Next time when posing a question please cut down your code down to a reasonable size getting rid of all the parts that are not really related to the question.

There are lots of examples of how to do this in the examples section of ?plot.zoo.(link) Define a panel function and put your code in there. For example, using the setup in the question

pnl <- function(x, y, ...) {

  lines(y ~ x)

  panel.number = parent.frame()$panel.number
  nser <- parent.frame()$nser
  if (panel.number == nser) {
     ticks <- seq(x[1], x[length(x)], by=90)
     axis(1, at = ticks, labels = letters[seq_along(ticks)])
  }
}

plot(tp, panel = pnl, xaxt = "n")

enter image description here

2) zoo also supports lattice plots and ggplot2 plots. Here is a ggplot2 plot via autoplot.zoo (link)

library(ggplot2)
at <- seq(start(tp), end(tp), by = 90)
autoplot(tp) + scale_x_date(breaks = at, labels = letters[seq_along(at)])

screenshot

you are trying to coerce text labels on a date axis hence there is no output. For custom text labels you need to convert xts/zoo to data.frame before plotting, plot data without any time index and provide custom labels in axis(1,...)

Code

With sample xts data

#Load sample xts/zoo data, lubridate for month/year functions

require(PerformanceAnalytics)
require(lubridate)
data(edhec)

#Convert to data.frame for plotting, keep data until Dec 1998 and single time series 

df<-data.frame(date=index(edhec[,1]['/1998']),edhec[,1]['/1998'],row.names=NULL)


#label break dates,monthly data,hence seq index = 3

ticks<-df$date[seq(1,length(df$date),3)]

#label breaks, at = seq(1,length(df$date),3)

#Map months to seasons (USA)
Month2Season<-function(mon){

Winter<-c(12,1,2)
Spring<-c(3,4,5)
Summer<-c(6,7,8)
Autumn<-c(9,10,11)

season<-NULL

if      (any(mon %in% Winter)) season="Winter"  
else if (any(mon %in% Spring)) season="Spring" 
else if (any(mon %in% Summer)) season="Summer" 
else if (any(mon %in% Autumn)) season="Autumn" 

return(season)
}

#get seasons for all label break dates

season_labels<-sapply(ticks,function(x) paste0(Month2Season(month(x)),"-",year(x)))

# provide numeric index for label breaks of at =

plot(df$Convertible.Arbitrage,type="l",xaxt="n")
axis(1,at=seq(1,length(df$date),3),labels=season_labels)

Plot enter image description here

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top