R - Plotting a time series with NA results with ggplot2 - r

I have a data set that contains power data taken every 20th of a second. The problem seems to lie with variable Moment.1 and Active_Power which contain NA values. The resulted plot of variable Moment appears fine. Below is my code and here is a screenshot of My data:
library(ggplot2)
library(scales)
library(reshape2)
Flatcsv <-"../FlatRock/data.csv"
FlatData <- read.csv(Flatcsv,sep = ",",na.strings = "NULL")
ggplot(FlatData, aes(x=strptime(Timestamp_EST,"%Y-%m-%d %H:%M:%OS"), ymax=50000)) +
geom_line(aes(y=Moment),col="blue") +
geom_line(aes(y=Active_Power), col="red") +
scale_x_datetime(name="Date/Time", breaks = date_breaks("1 min"),
labels = date_format(format = "%H:%M:%S \n %Y/%m/%d"),
minor_breaks = date_breaks("20 sec")) +
scale_y_continuous(limits=c(0,50000),name="Moment (kN*m)")
The only visible line is the plot of variable.
Any help would be greatly appreciated.

Related

Change order of dates in R ggplot?

I have been working on a plot in R using ggplot and plotting dates on the x axis. I have noticed that R does not recognize them as dates, and so the order on the x axis is wrong. I have tried many different things such as using as.Date(), manually editing levels and ordering the x axis, but nothing has worked. Here's my code:
library(dplyr)
library(ggplot2)
library(hrbrthemes)
calories_data = read.csv('dailyCalories_clean.csv',header = TRUE, sep=",")
ggplot(calories_data, aes(x= ActivityDay, y=Calories, group=Id, color = Id))+
geom_line()
Here's the plot
I appreciate any help, I'm new at this and have been researching for hours with no success. Thank you!
One option to fix your issue would be to convert your dates to proper dates to fix the order and use the date_labels argument of scale_x_date to format your dates. To convert to dates you have to add a fake year to your ActivityDay, e.g. "2022":
Using some fake random data to mimic your real data:
library(ggplot2)
set.seed(123)
calories_data <- data.frame(
ActivityDay <- rep(c("4/1", "4/10", "5/11", "5/1"), 3),
Id = rep(1:3, each = 4),
Calories = runif(12, 1000, 3000)
)
calories_data$ActivityDay <- as.Date(paste("2022", calories_data$ActivityDay, sep = "/"), format = "%Y/%m/%d")
ggplot(calories_data, aes(x= ActivityDay, y=Calories, group=Id, color = Id))+
geom_line() +
scale_x_date(date_breaks = "5 day", date_labels = "%m/%d")

ggplot2, x-axis not recognizing dates

Trying to plot the following data frame (call it bob):
1
Since the original date is in d/m/y, I use Finaldate and Value to graph.
Here is the code used to graph:
ggplot(Bob, aes(Finaldate, Value)) +geom_line() + geom_point(size = 3) +
labs(title = "TITLE",subtitle = "SUBTITLE", y = "Y", x = "X") +
theme_fivethirtyeight()+scale_y_continuous(name="name", labels = scales::comma)+theme(legend.title = element_blank())+scale_x_discrete(guide = guide_axis(check.overlap = TRUE))
While I do get an output, it is not as a time series but rather the dates are not in order and the plot makes no sense. Attached a copy of the plot as well.
enter image description here
Not sure how to fix this problem, and have tried a couple of different things
Have you tried using
+ scale_x_date(date_labels = "%d %m %Y") (ggplot2)
https://r-graph-gallery.com/279-plotting-time-series-with-ggplot2.html
You need to convert Finaldate to a date -- it is being treated as a character so all the dates are in "alphabetical" order. Try:
Bob$finalDate <- as.Date(Bob$finalDate, format = "%m/%d/%Y")

Show limited time range on x-axis with ggplot

I want the x-axis in the following graph to start at 06:00 and end at 22:00, with breaks at every 4 hours. I can't figure out the following, however.
a) How to make the x-axis start at 06:00 without any empty space before 06:00.
b) How to make the x-axis end at 22:00 without any empty space after 22:00. Right now it doesn't even show 22:00
c) How to have breaks at every 4 hours.
d) How to assign a label to the y-axis (currently it's simply X4, the column name).
I've tried several things, but without success. Some example data:
range <- seq(as.POSIXct("2015/4/18 06:00"),as.POSIXct("2015/4/18 22:00"),"mins")
df <- data.frame(matrix(nrow=length(range),ncol=4))
df[,1] <- c(1:length(range))
df[,2] <- 2*c(1:length(range))
df[,3] <- 3*c(1:length(range))
df[,4] <- range
Reshape:
library(reshape2)
df2 <- melt(df,id="X4")
Graph:
library(ggplot2)
ggplot(data=df2,aes(x=X4,y=value,color=variable)) + geom_line()+
scale_y_continuous(expand=c(0,0)) +
coord_cartesian(xlim=c(as.POSIXct("2015/4/18 06:00:00"),as.POSIXct("2015/4/18 22:00:00")))
Which makes the graph look like this:
Any ideas?
Here is some code that should help you. This can easily be done using scale_x_datetime.
## desired start and end points
st <- as.POSIXct("2015/4/18 06:00:00")
nd <- as.POSIXct("2015/4/18 22:00:00")
## display data for given time range
ggplot(data = df2, aes(x = X4, y = value, color = variable)) +
geom_line() +
scale_y_continuous("Some name", expand = c(0, 0)) +
scale_x_datetime("Some name", expand = c(0, 0), limits = c(st, nd),
breaks = seq(st, nd, "4 hours"),
labels = strftime(seq(st, nd, "4 hours"), "%H:%S"))

Ongoing dramas with epicurves date scales

I'm attempting to use ggplot and R for analysing some epidemiologic data, and I'm continuing to struggle with getting an epidemic curve to appear properly.
Data is here
attach(epicurve)
head(epicurve)
onset age
1 21/12/2012 18
2 14/06/2013 8
3 10/06/2013 64
4 28/05/2013 79
5 14/04/2013 56
6 9/04/2013 66
epicurve$onset <- as.Date(epicurve$onset, format="%d/%m/%Y")
ggplot(epicurve, aes(onset)) + geom_histogram() + scale_x_date(breaks=date_breaks("1 year"), minor_breaks=date_breaks("1 month"), labels = date_format("%b-%Y"))
gives this graph. This is fine, but the binwidths are not related to any time period of note, and adjusting them is a bit trial and error.
For this particular dataset, I'd like to display the cases by month of onset.
One way I worked out how to do this is:
epicurve$monyr <- format(epicurve$onset, "%b-%Y")
epicurve$monyr <- as.factor(epicurve$monyr)
ggplot(epicurve, aes(monyr)) + geom_histogram()
Outputs a graph I can't post because of the reputation system. The bars represent something meaningful, but the axis labels are a bomb-site. I can't format the axes using scale_x_date because they aren't dates and I can't work out what arguments to pass to scale_x_discrete to give useful labels.
I have a feeling there should be an easier way to do this by doing an operation on the onset column. Can anyone give me any pointers, please?
One option is to aggregate the data outside ggplot and then use geom_bar. This will produce counts by month.
edited Sept. 21 2013. Altered plot to show months with no counts.
epicurve <- read.csv("epicurve.csv", sep=",", header=T)
# initial formatting
epicurve$onset <- as.Date(epicurve$onset, format="%d/%m/%Y") # convert to Date class
epicurve$onset <- strftime(epicurve$onset, format="%Y/%m") # convert to Year-month
epicurve$onset <- paste(epicurve$onset, "/01", sep = "") # add arbitrary day on to end to make compatible w/ ggplot2
# aggregate by month
onset_counts <- aggregate(epicurve$onset, by = list(date = epicurve$onset), length) # aggregate by month
onset_counts$date = as.Date(onset_counts$date, format = "%Y/%m/%d") # covert to Date class
# plot
library(ggplot2)
library(scales)
ggplot(onset_counts, aes(x=date, y=x)) + geom_bar(stat="identity") + theme_bw() + theme(axis.text.x = element_text(angle=90, hjust = 1, vjust = 1)) +
ylab("Frequency") + xlab(NULL) + scale_x_date(breaks="month", labels=date_format("%Y-%m"))
I've also just happened across another way of making it look pretty, although it feels like a bit of a kludge.
#read data
epicurve <- read.csv("epicurve.csv", sep=",", header=T)
epicurve$onset <- as.Date(epicurve$onset, format="%d/%m/%Y")
#load libraries
library(ggplot2)
library(scales)
#plot
ggplot(epicurve, aes(onset)) + geom_histogram(colour="white", binwidth=30.4375) +
scale_x_date(breaks=date_breaks("1 year"), minor_breaks=("1 month"), labels=date_format("%b-%Y")) +
scale_y_continuous(breaks=0:10, minor_breaks=NULL) +
theme(axis.text.x = element_text(angle=45, vjust=0.5))
# binwidth = (365.25/12) = 30.4375 - which nicely makes the bins fit the scale nicely
Which gives this (notice the beautiful alignment of the bins!):
Many thanks to Nate for the help, and hopefully this will be useful!

Trouble with placing and formatting dates in ggplot2 graph using chron

I've been trying to add appropriate dates on the x-axis of my graph, but can't figure out how to do it in a sane way. What I want is pretty simple: a date at every January 1st in between the minimum and maximum of my data set.
I don't want to include the month - just '2008' or '2009' or whatever is fine. A great example would be this graph:
example graph
Except I want the date on every year, rather than every other year.
I can't seem to figure this out. My dates are defined as days since 1/1/1970, and I've included a method dateEPOCH_formatter which converts the epoch format to a format using the chron package. I've figured out how to make a tick mark and date at the origin of the graph and every 365 days thereafter, but that's not quite the same thing.
Another minor problem is that, mysteriously, the line chron(floor(y), out.format="mon year",origin.=epoch) outputs a graph with axis markers like 'Mar 2008', but changing the line to chron(floor(y), out.format="year",origin.=epoch) doesn't give me a result like '2008' - it just results in the error:
Error in parse.format(format[1]) : unrecognized format year
Calls: print ... as.character.times -> format -> format.dates -> parse.format
Execution halted
Here's my code - thanks for the help.
library(ggplot2)
library(chron)
argv <- commandArgs(trailingOnly = TRUE)
mydata = read.csv(argv[1])
png(argv[2], height=300, width=470)
timeHMS_formatter <- function(x) { # Takes time in seconds from midnight, converts to HH:MM:SS
h <- floor(x/3600)
m <- floor(x %% 60)
s <- round(60*(x %% 1)) # Round to nearest second
lab <- sprintf('%02d:%02d', h, m, s) # Format the strings as HH:MM:SS
lab <- gsub('^00:', '', lab) # Remove leading 00: if present
lab <- gsub('^0', '', lab) # Remove leading 0 if present
}
dateEPOCH_formatter <- function (y){
epoch <- c(month=1,day=1,year=1970)
chron(floor(y), out.format="mon year",origin.=epoch)
}
p= ggplot() +
coord_cartesian(xlim=c(min(mydata$day),max(mydata$day)), ylim=c(0,86400)) + # displays data from first email through present
scale_color_hue() +
xlab("Date") +
ylab("Time of Day") +
scale_y_continuous(label=timeHMS_formatter, breaks=seq(0, 86400, 14400)) + # adds tick marks every 4 hours
scale_x_continuous(label=dateEPOCH_formatter, breaks=seq(min(mydata$day), max(mydata$day), 365) ) +
ggtitle("Email Sending Times") + # adds graph title
theme( legend.position = "none", axis.title.x = element_text(vjust=-0.3)) +
theme_bw() +
layer(
data=mydata,
mapping=aes(x=mydata$day, y=mydata$seconds),
stat="identity",
stat_params=list(),
geom="point",
geom_params=list(alpha=5/8, size=2, color="#A9203E"),
position=position_identity(),
)
print(p)
dev.off()
I think it will be much easier to use the built in function scale_x_date with date_format and date_breaks from the scales package. These should work with most date classes in R, such as Date, chron etc
for example
library(ggplot2)
library(chron)
library(scales)
# some example data
days <- seq(as.Date('01-01-2000', format = '%d-%m-%Y'),
as.Date('01-01-2010', format = '%d-%m-%Y'), by = 1)
days_chron <- as.chron(days)
mydata <- data.frame(day = days_chron, y = rnorm(length(days)))
# the plot
ggplot(mydata, aes(x=days, y= y)) + geom_point() +
scale_x_date(breaks = date_breaks('year'), labels = date_format('%Y'))
To show how intuitive and easy these function are, if you wanted Montth-year labels every 6 months - note that this requires a very wide plot or very small axis labels
ggplot(mydata, aes(x=days, y= y)) + geom_point() +
scale_x_date(breaks = date_breaks('6 months'), labels = date_format('%b-%Y'))

Resources