Consider the following:
set.seed(1)
RandData <- rnorm(100,sd=20)
Locations <- rep(c('England','Wales'),each=50)
today <- Sys.Date()
dseq <- (seq(today, by = "1 days", length = 100))
Date <- as.POSIXct(dseq, format = "%Y-%m-%d")
Final <- cbind(Loc = Locations, Doy = as.numeric(format(Date,format = "%j")), Temp = RandData)
In this example how is it possible to produce two plots in the same figure window, where the first plot shows the temperature in England against Doy and the second shows temperature in Wales against Doy?
Note that your data is a character matrix. Better if the Final object is created via:
Final <- data.frame(Loc = Locations,
Doy = as.numeric(format(Date,format = "%j")),
Temp = RandData)
With that, the code below draws two plots on the one window, side by side. I use the formula interface to plot() to make use of it's subset argument, which works like the subset() function.
ylab <- "Temperature"
xlab <- "Day of year"
layout(matrix(1:2, ncol = 2))
plot(Temp ~ Doy, data = Final, subset = Loc == "England", main = "England",
ylab = ylab, xlab = xlab)
plot(Temp ~ Doy, data = Final, subset = Loc == "Wales", main = "Wales",
ylab = ylab, xlab = xlab)
layout(1)
Which produces this plot:
If you want them both on the same scale then we modify it a bit:
ylab <- "Temperature"
xlab <- "Day of year"
xlim <- with(Final, range(Doy))
ylim <- with(Final, range(Temp))
layout(matrix(1:2, ncol = 2))
plot(Temp ~ Doy, data = Final, subset = Loc == "England", main = "England",
ylab = ylab, xlab = xlab, xlim = xlim, ylim = ylim)
plot(Temp ~ Doy, data = Final, subset = Loc == "Wales", main = "Wales",
ylab = ylab, xlab = xlab, xlim = xlim, ylim = ylim)
layout(1)
which produces this version of the plot
For a line-plot you'd need to get the data in Doy order and then add type = "l" to the plot() calls.
For completeness, #Justin has shown how to use one of the high level plotting packages to achieve something similar but with less user-effort via ggplot2. The lattice package is another major high-level plotting package in R. You can achieve the same plot using lattice via:
require(lattice)
xyplot(Temp ~ Doy | Loc, data = Final, type = c("l","p")
The latter produces
Use type = "p" for just points and type = "l" for just lines. As you can see, the higher-level packages make producing these plots a bit easier than with the base graphics package.
by using cbind to create your data, they are all coerced to character. instead use data.frame()
Final <- data.frame(Loc = Locations,
Doy = as.numeric(format(Date,format = "%j")),
Temp = RandData)
ggplot does things like this very nicely.
library(ggplot2)
ggplot(Final, aes(x=Doy, y=Temp)) + geom_path() + facet_wrap( ~ Loc)
Or you can use coloring:
ggplot(Final, aes(x=Doy, y=Temp, color=Loc)) + geom_path()
Related
i'm using the package 'latticeExtra' to plot with double Y axis as i show in my code:
library(latticeExtra)
MS <- xyplot(Tabla.Rosetta.dt[,14] ~ Tabla.Rosetta.dt[,1], Tabla.Rosetta.dt, type='l', col="#9933CC", ylab = 'Meteoscore',
key=list(space="topright",
lines=list(col=c("#9933CC","#FF9933"), lty=c(1,1), lwd=6),
text=list(c("Meteoscore"," RSP"))
))
RSP <- xyplot(Tabla.Rosetta.dt[,2] ~ Tabla.Rosetta.dt[,1], Tabla.Rosetta.dt, type='l', col="#FF9933", ylab = 'RSP frequency', xlab = 'Dates')
doubleYScale(MS, RSP, add.ylab2 = TRUE, use.style=FALSE)
but the input 'key' doesn't work. I would like add legend in topright but i don't know how do ir.
ideas?
Thanks for your time
Please read the info at the top of the r tag and note that all questions should be reproducible. Tabla.Rosetta.dt is missing so in the absence of that we will use the SeatacWeather data frame from latticeExtra and adjust the example to that adding panel.key in a new layer specifying packets=3 to the layer.
library(latticeExtra)
data(SeatacWeather)
temp <- xyplot(max.temp + min.temp ~ day | month,
data = SeatacWeather, type = "l", layout = c(3, 1))
rain <- xyplot(precip ~ day | month, data = SeatacWeather, type = "h")
doubleYScale(temp, rain, style1 = 0, style2 = 3, add.ylab2 = TRUE) +
layer(panel.key(text = c("max temp", "min temp", "rain"),
lines = TRUE, points = FALSE),
packets = 3)
I would like to plot graphs with multiple lines in R like this:
2 lines
x axis is date
y axis is the log return
I have data in 3 vectors
print(class(TradeDate))
print(class(ArimaGarchCurve))
print(class(CompareCurve))
---------------------------------------------
[1] "factor"
[1] "numeric"
[1] "numeric"
I search and found that xyplot may be useful, but I don't know how to use it. I have tried.
pdf("Testing.pdf")
plotData <- data.frame(Date=TradeDate,
Arima=ArimaGarchCurve,
BuyHold=BuyHoldCurve)
print(xyplot(
Arima ~ Date,
data=plotData,
superpose=T,
col=c("darkred", "darkblue"),
lwd=2,
key=list(
text=list(
c("ARIMA+GARCH", "Buy & Hold")
),
lines=list(
lwd=2, col=c("darkred", "darkblue")
)
)
))
dev.off()
Here is the result:
Learn from here
Thank you very much.
dput(head(plotData,20))
structure(list(Date = structure(1:20, .Label = c("2001-12-03",
"2001-12-04", "2001-12-05", "2001-12-06", "2001-12-07", "2001-12-10",
"2001-12-11", "2001-12-12", "2001-12-13", "2001-12-14", "2001-12-17",
"2001-12-18", "2001-12-19", "2001-12-20", "2001-12-21", "2001-12-24",
"2001-12-25", "2001-12-26", "2001-12-27", "2001-12-28", "2001-12-31",
"2002-01-01", "2002-01-02", "2002-01-03", "2002-01-04", "2002-01-07",
"2019-05-22", "2019-05-23"), class = "factor"), Arima = c(-0.0134052258713131,
-0.00542641764174324, 0.0128513670753771, 0.0282761455973665,
0.0179931884968989, 0.0281714817318116, 0.0435962602538011, 0.0462004298658309,
0.0194592964361352, 0.0248069155406948, 0.032807001046888, 0.0381120657516546,
0.0381120657516546, 0.030090589527961, -0.0146168717909267, -0.00630652663076437,
-0.00630652663076437, -0.00630652663076437, 0.0100429785563596,
0.0100429785563596), BuyHold = c(-0.0134052258713131, -0.00542641764174324,
0.0128513670753771, 0.0282761455973665, 0.0384544388322794, 0.0281714817318116,
0.0125050470584384, 0.0151092166704679, -0.0116319167592278,
-0.0170082867113405, -0.0090082012051471, -0.00370313650038065,
-0.00370313650038065, -0.0117246127240743, -0.056432074042962,
-0.0481217288827996, -0.0481217288827996, -0.0481217288827996,
-0.0317722236956757, -0.0317722236956757)), row.names = c(NA,
20L), class = "data.frame")
I think that this could help:
library(lattice)
xyplot(
Arima + BuyHold ~ Date, # here you can add log() to the two ts
data=plotData,
superpose=T,
col=c("#cc0000", "#0073e6"), # similar colors
lwd=2,
key=list(
text = list(c("ARIMA+GARCH log", "Buy & Hold log")),
lines = list( lwd=2, col=c("#cc0000", "#0073e6")) # similar colors
), type=c("l","g") # lines and grid
)
If you want to reduce the number of ticks on the x axis, you'd create your labels, and add them in this way (in this case, one year, you'd calculate your full time series parameters):
x.tick.number <- 1
at <- seq(1, nrow(d), length.out=x.tick.number)
labels <- round(seq(2001, 2001, length.out=x.tick.number))
In the plot:
xyplot(
Arima + BuyHold ~ Date, # here you can add log() to the two ts
data=d,
superpose=T,
col=c("#cc0000", "#0073e6"),
lwd=2,
key=list(
text = list(c("ARIMA+GARCH log", "Buy & Hold log")),
lines = list( lwd=2, col=c("#cc0000", "#0073e6"))
), type=c("l","g"),
scales = list(at=at, labels=labels, rot=90))
Both lattice and ggplot offer solutions. Regardless, as #davide suggests, "melting" your data or converting it from a "wide" format to a "long" is a very good practice. Values of interest are placed in a single variable and a parallel factor is created to identify the group associated with each value.
This can be done in base R by several methods. The use of stack() is shown here. In addition, by converting the factor or character representation of the date into a Date object, the plotting routines in lattice and ggplot2 will do a better job managing axes labels for you.
df <- data.frame(Date = as.Date(plotData$Date), stack(plotData[2:3]))
(names(df)) # stack names the data 'values and the grouping factor 'ind'
levels(df$ind) <- c("ARIMA+GARCH", "Buy & Hold") # simplifies legends
Here's a somewhat simple plot with few additions for grid lines and legend (key):
xyplot(values ~ Date, data = df, groups = ind, type = c("g", "l"), auto.key = TRUE)
The plots can be customized with lattice through panel functions and elements in auto.key. Although using col = c("darkred", "darkblue") at the top level of the function would color the lines in the plot, passing it through the optional par.settings argument makes it available for the legend function.
xyplot(values ~ Date, data = df, groups = ind,
panel = function(...) {
panel.grid(h = -1, v = -1)
panel.refline(h = 0, lwd = 3)
panel.xyplot(..., type = "l")},
auto.key = list(points = FALSE, lines = TRUE, columns = 2),
par.settings = list(superpose.line = list(col = c("darkred", "darkblue"))))
I've been searching for ways to make overlapping grouped histograms with the function 'histogram' in lattice, which I've found an answer to here.
histogram( ~Sepal.Length,
data = iris,
type = "p",
breaks = seq(4,8,by=0.2),
ylim = c(0,30),
groups = Species,
panel = function(...)panel.superpose(...,panel.groups=panel.histogram,
col=c("cyan","magenta","yellow"),alpha=0.4),
auto.key=list(columns=3,rectangles=FALSE,
col=c("cyan","magenta","yellow3"))
)
Now my question is if you could still add normal distributions for every group to this plot.
Possibly using this?
panel.mathdensity(dmath = dnorm, col = "black",
args = list(mean=mean(x),sd=sd(x)))
end result should end up looking similar to this:
image
This is the closest I was able to get. The hint I used was here. My problem is that the density plot gets hidden behind the next histogram plot.
plot1 <- histogram( ~Sepal.Length,
data = iris,
type = "p",
ylim = c(0,30),
breaks = seq(4,8,by=0.2),
groups = Species,
col=c("cyan","magenta","yellow"),
panel = panel.superpose,
panel.groups = function(x,y, group.number,...){
specie <- levels(iris$Species)[group.number]
if(specie %in% "setosa"){
panel.histogram(x,...)
panel.mathdensity(dmath=dnorm,args = list(mean=mean(x), sd=sd(x)), col="black")
}
if(specie %in% "versicolor"){
panel.histogram(x,...)
panel.mathdensity(dmath=dnorm,args = list(mean=mean(x), sd=sd(x)), col="black")
}
if(specie %in% "virginica"){
panel.histogram(x,...)
panel.mathdensity(dmath=dnorm,args = list(mean=mean(x), sd=sd(x)), col="black")
}
}
)
I've done a conditional boxplot with my data, with the bwplot function of the lattice library.
A1 <- bwplot(measure ~ month | plot , data = prueba,
strip = strip.custom(bg = 'white'),
cex = .8, layout = c(2, 2),
xlab = "Month", ylab = "Total",
par.settings = list(
box.rectangle = list(col = 1),
box.umbrella = list(col = 1),
plot.symbol = list(cex = .8, col = 1)),
scales = list(x = list(relation = "same"),
y = list(relation = "same")))
Then, I've done a xyplot because I want to add the precipitation data to the previous graph, using xyplot from lattice library also.
B1 <- xyplot(precip ~ month | plot, data=prueba,
type="b",
ylab = '% precip',
xlab = 'month',
strip = function(bg = 'white', ...)
strip.default(bg = 'white', ...),
scales = list(alternating = F,
x=list(relation = 'same'),
y=list(relation = 'same')))
I've try to draw them on the same graph using grid.arrange from gridExtra library:
grid.arrange(A1,B1)
But with this, I don't overlap the data, but the result is this
How could I draw the precipitacion data "inside" the boxplots conditioned by plot?
Thank you
Using the barley data as Andrie did, another approach with latticeExtra:
library(lattice)
library(latticeExtra)
bwplot(yield ~ year | variety , data = barley, fill = "grey") +
xyplot(yield ~ year | variety , data = barley, col = "red")
You need to create a custom panel function. I demonstrate with the built-in barley data:
Imagine you want to create a simple bwplot and xyplot using the barley data. Your code might look like this:
library(lattice)
bwplot(yield ~ year | variety , data = barley)
xyplot(yield ~ year | variety , data = barley)
To combine the plots, you need to create a panel function that first plots the default panel.bwplot and then the panel.xyplot. Try this:
bwplot(yield ~ year | variety , data = barley,
panel = function(x, y, ...){
panel.bwplot(x, y, fill="grey", ...)
panel.xyplot(x, y, col="red", ...)
}
)
There is some information about doing this in the help for ?xyplot - scroll down to the details of the panel argument.
I have to plot a physical variable over a world map at differents moments. So i have to make many plot as how many moments i have to plot. The problem is that my routine set the end of the scale by default, and this make the reading of the plot difficult. I would like to fix the end of the scale, in order to have one scale for all the plots. This is piece of an old code i would reuse
require(reshape)
require(mapdata)
require(mapproj)
df <- read.table('/media/Lacie2/dati/hy.dat',head=F)
names(df) <- c("value", "x", "y")#, "t")
dfc <- cast(df[ ,-4], x ~ y)
mm<-as.matrix(dfc,ncol=480,nrow=241)
filled.contour(x=seq(0,360,length.out=480),y=seq(-90,90,length.out=241),mm,
color.palette = colorRampPalette(c("lightblue", "blue","violet", "black")),
xlab = "Longitude (°)", ylab = "Latitude (°)",
plot.axes = {axis(1); axis(2);
map('world2Hires',
xlim = c(0, 360),
ylim = c(-90, 90),
add = T, col = "black")}
)
I don't understand how to fix the endscale of the ladder. How can i do it?
If you want to plot colors only up to a maximum, then just 'trim' the value that you pass to the plot routine with:
df$trimval <- pmin(df$value, 2)
# the range in the example below is roughly -4.5 to 4.5
... and plot using that value as the z-argument to contour.plot. Indented code and random "value" argument below:
require(reshape)
require(mapdata)
require(mapproj)
df <- data.frame(value=rnorm( 480*241), x=seq(0,360,length.out=480),y=seq(-90,90,length.out=241) )
df$trimval <- pmin(df$value, 2)
dfc <- cast(df[-1], x ~ y)
mm<-as.matrix(dfc,ncol=480,nrow=241)
filled.contour(x=seq(0,360,length.out=480),y=seq(-90,90,length.out=241),mm,
color.palette = colorRampPalette(c("lightblue", "blue","violet", "black")),
xlab = "Longitude (°)", ylab = "Latitude (°)",
plot.axes = {axis(1); axis(2);
map('world2Hires',
xlim = c(0, 360),
ylim = c(-90, 90),
add = T, col = "black")}
)
The color range is therefore maxxed out at 2 and all of the values above 2 are plotted with the color given to 2. (I might mention that I tried using zlim and the results were not as I imagined you would want.)