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.
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
精彩评论