I have gas meter readings over three years which I'm trying to graph in R, to highlight the changing daily usage over the months in a year, and to compare different years' usage.
Data sample:
Date,Gas
02/01/2010,4460.9
13/01/2010,4543
04/02/2010,4656
16/02/2010,4733
07/03/2010,4842
26/03/2010,4933.8
I can calculate the average daily usage from the periodic readings, and plot the whole of the data across several years as a single data series:
A <- read.table("energy.csv", header=TRUE, fill=TRUE, sep=',')
A$Dates <- as.Date(A$Date, format="%d/%m/%Y")
for (j in 2:length(A$Gas)) {
A$GasDiff[j-1] = A$Gas[j] - A$Gas[j-1]
}
plot(A$Dates, A$GasDiff, type="o", lty=1, pch=20, ylab="Daily Consumption",
main="Gas Consumption")
But I can't figure out how to get R to automatically split the data into different ?frames? for each year, so that I can plot separate lines for each year. I can manually create different input files with just the data for each year, but it's inelegant, and will need the code changed every year.
I'm sure it's a simple question, but I've stared at manuals, and can't figure it out.
Select Plot > Multi-Panel/Axis: Multiple Y Axes.... Click the Multiple Y Axes... button on the 2D Graphs toolbar. Origin opens the plotmyaxes dialog box.
Use the yyaxis function to create a plot with two y-axes. For example, you can use two y-axes to plot two lines on different scales.
In an Excel chart, can I have different Y-axis scales (a primary and secondary axis)? Yes, in Excel 2013 and Excel 2016 you can have two axes. Start by creating a chart with just one axis.
To draw multiple curves in one plot, different functions are created separately and the curve() function is called repeatedly for each curve function. The call for every other curve() function except for the first one should have added an attribute set to TRUE so that multiple curves can be added to the same plot.
There's no need to split the data into data-frames by year; you can use the ggplot2
package quite easily to differentiate the plots by year. First I'll make up some data:
dts <- as.Date("20050101", '%Y%m%d') + seq(0,1000,15)
A <- data.frame( Dates = dts, Gas = 4000 + cumsum(abs( rnorm(length(dts), 100, 30))))
Next I'll add two columns to A
: DayOfYear
which is the "day-number" within the year, and the GasDiff
column (same as yours but generated more easily, with no loops!):
A <- transform( A,
Year = format(Dates, '%Y'),
DayOfYear = as.numeric( format(Dates, '%j')),
GasDiff = c(diff( Gas ),NA))
Next we use ggplot2
to first plot all the years one after the other, but with different colors:
require(ggplot2)
ggplot(A, aes(Dates, GasDiff)) + geom_line( aes(colour = Year))
which gives you this:
Alternatively you can plot the different years in a vertical grid:
ggplot(A, aes(DayOfYear, GasDiff)) + geom_line( ) + facet_grid(Year ~ .)
and you get this:
UPDATE: A third way is to plot all the years on the same plot with different colors/points, which may be useful if you are looking for seasonal patterns (but looks bad in my case because I made up random data).
ggplot(A, aes(DayOfYear, GasDiff)) +
geom_line( aes(colour = Year) ) +
geom_point( aes(shape = Year))
Here are the plots corresponding to Prasad's ggplot examples (1) done using xyplot
in lattice. (2) After that we show how to do it using xyplot.zoo
from the zoo package and then (3) we show how to do each yet again using the plot.zoo
which uses the zoo package's classic graphics facilities.
In each of these cases we also show a 4th style which is based on xblocks
.
First lets repeat Prasad's setup:
dts <- as.Date("20050101", '%Y%m%d') + seq(0,1000,15)
A <- data.frame( Dates = dts, Gas = 4000 + cumsum(abs( rnorm(length(dts), 100, 30))))
A <- transform( A,
Year = format(Dates, '%Y'),
DayOfYear = as.numeric( format(Dates, '%j')),
GasDiff = c(diff( Gas ),NA))
Now lets try using lattice
library(lattice) # xyplot
library(latticeExtra) # layer_, panel.xblocks
library(gridExtra) # grid.arrange
library(RColorBrewer) # brewer.pal
png("png1.png")
p1 <- xyplot(GasDiff ~ Dates, group = Year, A, type = "l",
par.settings = list(superpose.line = list(col = 1:nlevels(A$Year))),
auto.key = list(lines = TRUE, points = FALSE))
p2 <- xyplot(GasDiff ~ DayOfYear | Year, A, type = "l", layout = c(1, 3))
p3 <- xyplot(GasDiff ~ DayOfYear, A, group = Year, type = "l",
auto.key = list(lines = TRUE, points = FALSE))
# and here is another style:
myPalette <- brewer.pal(nlevels(A$Year), "Set3")
p4 <- xyplot(GasDiff ~ Dates, A, type = "l", col = 1) +
layer_(panel.xblocks(A$Dates, myPalette[A$Year]))
grid.arrange(nrow = 2, p1, p2, p3, p4)
dev.off()
This gives these 4 plots:
and now lets repeat this using using zoo in conjunction with the lattice and the other packages:
png("png2.png")
library(zoo)
library(lattice)
library(latticeExtra) # layer_, panel.xblocks
library(gridExtra) # grid.arrange
library(RColorBrewer) # brewer.pal
z <- with(A, zoo(GasDiff, Dates))
year <- format(time(z), "%Y")
# split years into separate columns and plot
P1 <- xyplot(do.call("merge", split(z, year)), screen = 1, col = 1:3)
# split years into separate columns and use day.of.year as time
day.of.year <- function(x) as.numeric(format(x, "%j"))
zz <- read.zoo(A[c(1, 5, 3)], FUN = day.of.year, split = 3)
colnames(zz) <- unique(year)
P2 <- xyplot(na.approx(zz, na.rm = FALSE))
P3 <- xyplot(na.approx(zz, na.rm = FALSE), screen = 1, col = 1:3, auto.key = TRUE)
pal <- brewer.pal(nlevels(factor(year)), "Set3")
P4 <- xyplot(z, screen = 1) + layer_(panel.xblocks(time(z), pal[factor(year)]))
grid.arrange(nrow = 2, P1, P2, P3, P4)
dev.off()
Here is the output:
A third set of ways is to use classic graphics with zoo where we use the same z
, zz
and pal
calculated above:
library(zoo)
library(RColorBrewer) # brewer.pal
png("png3a.png")
plot(do.call("merge", split(z, year)), screen = 1, col = 1:3)
dev.off()
png("png3b.png")
plot(na.approx(zz, na.rm = FALSE))
dev.off()
png("png3c.png")
plot(na.approx(zz, na.rm = FALSE), screen = 1, col = 1:3)
legend("topleft", colnames(zz), lty = 1, col = 1:3, bty = "n")
dev.off()
png("png3d.png")
plot(z, type = "n")
xblocks(time(z), pal[factor(year)])
lines(z)
dev.off()
and here is the output
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With