Formatting dates in ggplot horizontal bar graph - r

I want to make a horizontal bar chart with dates on the x axis using ggplot. Here is the code I have:
df <- data.frame(patient= c('Harry','John'), pain_date = c( as.POSIXct('13-04-2000', format = '%d-%m-%Y'), as.POSIXct('12-02-2000', format = '%d-%m-%Y') ), agony_date = c(as.POSIXct('25-05-2000', format = '%d-%m-%Y'),as.POSIXct('21-05-2000', format = '%d-%m-%Y')), death_date = c(as.POSIXct('30-06-2000', format = '%d-%m-%Y'), as.POSIXct('23-11-2000', format = '%d-%m-%Y')))
ggplot(df, aes(x=patient)) +
geom_linerange(aes(ymin=pain_date, ymax=agony_date), color="red", size=5) +
geom_linerange(aes(ymin=agony_date, ymax=death_date), color="black", size=5) +
coord_flip()
The question is how to fix the limit from JAN to DEC and how to put a tick at every first day of a month?
I've tried several things like:
scale_x_datetime(major="months")
scale_x_datetime(lim = c(as.POSIXct("01-01-2000"), as.POSIXct("31-12-2000")))
but it gives me the following error message:
Erreur : Invalid input: date_trans works with objects of class Date only
Thanks for your help

Summarizing the comments above, your code should look something like this:
require(scales)
df[, "pain_date"] <- as.Date(df[, "pain_date"])
df[, "agony_date"] <- as.Date(df[, "agony_date"])
df[, "death_date"] <- as.Date(df[, "death_date"])
ggplot(df, aes(x=patient)) +
geom_linerange(aes(ymin=pain_date, ymax=agony_date), color="red", size=5) +
geom_linerange(aes(ymin=agony_date, ymax=death_date), color="black", size=5) +
coord_flip() + scale_y_date(lim = c(as.Date("2000-01-01"), as.Date("2000-12-31")),
breaks=date_breaks(width = "1 month"))

Related

Using geom_segment to connect a line to the y-axis

I want to use geom_segment to make a line intercept the y-axis, the problem I am experiencing becomes readily apparent. Starting off with sample data:
dat <- data.frame(Yaxis = c(100,200,300,400,500,600,700,800), Year = c(2012,2013,2014,2015,2016,2017,2018,2019))
p <- ggplot(data=dat, aes(x=Year)) + geom_line(aes(y=Yaxis))
and adding a geom_segment layer produces:
p + geom_segment(aes(x=0,xend=2012,y=75,yend=100))
my attempts to amend this haven't worked out so far:
p + geom_segment(aes(x=0,xend=2012,y=75,yend=100)) + scale_x_continuous(expand= c(0,0), breaks = c(2012,2013,2014,2015,2016,2017,2018,2019))
For reference, here is a crude drawing of what I intend the graph to look like:
Thanks to #Sathish 's answer, I was able to create the graph I intended using
ggplot(data=dat, aes(x=as.Date(paste(Year,'-01-01', sep=""), "%Y-%m-%d"), y=Yaxis)) +
geom_line() +
geom_segment(aes(
x=as.Date("2011-01-01", "%Y-%m-%d"),
xend=as.Date("2012-01-01", "%Y-%m-%d"),
y=75,
yend=100), color = "red") +
scale_x_date(expand = c(0,0))
Convert Year column to Date class.
library('ggplot2')
ggplot(data=dat, aes(x=as.Date(paste(Year, '-01-01', sep = ""), "%Y-%m-%d"), y=Yaxis)) +
geom_line() +
geom_segment(aes(x=as.Date("2012-01-01", "%Y-%m-%d"),xend=as.Date("2020-01-01", "%Y-%m-%d"),y=75,yend=100), color = "red") +
xlab(label = "Year")

How to format difftime as hh:mm in ggplot2?

I want to display difftime data with ggplot2 and I want the tick format to be hh:mm.
library(ggplot2)
a= as.difftime(c("0:01", "4:00"), "%H:%M", unit="mins")
b= as.difftime(c('0:01', "2:47"), "%H:%M", unit="mins")
ggplot(data=NULL, aes(x=b, y=a)) + geom_point(shape=1) +
scale_x_time(labels = date_format("%H:%M"),
breaks = "1 hour")
But I get the following warning:
Don't know how to automatically pick scale for object of type difftime. Defaulting to continuous.
Warning message:
In structure(as.numeric(x), names = names(x)) : NAs introduced by coercion
and this as a graph:
Update:
my example was too minimal, I also need to be able to display negative differences, so this would be better data:
a= as.difftime(c(-60, -4*60), unit="mins")
b= as.difftime(c(-60, 2*60+47), unit="mins")
ggplot(data=NULL, aes(x=b, y=a)) + geom_point(shape=1)
The answer has two parts.
Plotting difftime objects
According to help("scale_x_time"), ggplot2 supports three date/time classes: scale_*_date for dates (class Date), scale_*_datetime for datetimes (class POSIXct), and scale_*_time for times (class hms). The last one is what we need here.
Class hms is a custom class for difftime vectors. as.hms() has a method for difftime. So. difftime objects can be plotted with ggplot2 by coercing to class hms:
a <- as.difftime(c(-60, -4 * 60), unit = "mins")
b <- as.difftime(c(-60, 2 * 60 + 47), unit = "mins")
library(ggplot2)
ggplot(data = NULL, aes(x = hms::as.hms(b), y = hms::as.hms(a))) +
geom_point(shape = 1)
Please, note that negative time differences are shown as well.
Formatting the tick labels
The OP has requested that tick marks should be labeled in hh:mm format. Apparently, the default formatting is hh:mm:ss. This can be modified by specifying a function that takes the breaks as input and returns labels as output to the labels parameter of the scale_x_time() and scale_y_time() functions:
format_hm <- function(sec) stringr::str_sub(format(sec), end = -4L)
ggplot(data = NULL, aes(x = hms::as.hms(b), y = hms::as.hms(a))) +
geom_point(shape = 1) +
scale_x_time(name = "b", labels = format_hm) +
scale_y_time(name = "a", labels = format_hm)
The format_hm() function truncates the :ss part from the default format. In addition, the axis are labeled nicely.
Depending on your constraints, you might consider translating the difftimes to distinct datetimes, which ggplot can handle just fine:
library(lubridate)
a_date_times <- floor_date(Sys.time(), "1 day") + a
b_date_times <- floor_date(Sys.time(), "1 day") + b
ggplot(data=NULL, aes(x=a_date_times, y=b_date_times)) +
geom_point(shape=1)
My best approach so far is:
library(ggplot2)
library(lubridate)
a= as.difftime(c(-60, -4*60), unit="mins")
b= as.difftime(c(-60, 2*60+47), unit="mins")
xbreaks = seq(ceiling(min(b)/60), floor(max(b)/60)) * 60
ybreaks = seq(ceiling(min(a)/60), floor(max(a)/60)) * 60
ggplot(data=NULL, aes(x=b, y=a)) + geom_point(shape=1) +
scale_x_continuous(labels = f, breaks = xbreaks) +
scale_y_continuous(labels = f, breaks = ybreaks)
f <- function(x){
t = seconds_to_period(abs(x)*60)
r = sprintf("% 2i:%02i", sign(x)*hour(t), minute(t))
return(r)
}

Change x-axis names in ggplot

I am not very good in R, and need some help.
My ggplot has a lot of dates(in the x-axis) so you can't actually see the dates, and I want to change it to months to give a better overview of the plot.
For example to something like this in the link:
Display the x-axis on ggplot as month only in R
This is the script I'm using:
r <- read.csv("xxdive.csv", header = T, sep = ";")
names(r) <- c("Date", "Number")
r <- data.frame(r)
r$Date <- factor(r$Date, ordered = T)
r[1:2, ]
Date Number
16.02.2015 97
17.02.2015 47
library(tidyverse)
ggplot(r, aes(Date, Number)) +
theme_light() +
ggtitle("16.02.15-10.02.16") +
ylab("Dives") +
geom_line(aes(group = 1), color = "blue")
This shows what kind of data I have.
I have tried using scale etc, but I can't make it work..
I hope this was understandable, and that someone can help me!! :)
I would convert column Date to data type Date
r$Date <- as.Date(r$Date, "%d.%m.%Y");
instead of converting it to data type factor.
r$Date <- factor(r$Date, ordered = T);
It's a little tricky without a working example, but try this.
install.packages("tidyverse")
library(tidyverse)
r <- read_delim("xxdive.csv", ";", col_types = list(col_date(), col_integer()))
names(r) <- c("Date", "Number")
ggplot(r, aes(Date, Number)) +
geom_line(aes(group = 1), color = "blue") +
scale_x_date(date_breaks = "1 month") +
ylab("Dives") +
ggtitle("16.02.15-10.02.16") +
theme_light()

R - using ggplot for line chart - no line showing

I'm using ggplot and geom_line but there is no line showing up.
I used this command:
library(ggplot2)
ggplot(campaigns, aes(x=Send.Time, y=Open.Rate, color='red')) + geom_line()
Please see screenshot below
You should remove "%" from the string and convert into numeric. Please see the code below:
# Simulation
library(lubridate)
library(dplyr)
campaigns <- data.frame(
Send.Time = c("5/30/17", "6/1/17", "6/1/17", "6/6/17", "6/8/17", "6/15/17"),
Open.Rate = c("33.40%", "9.14%", "29.64%", "24.90%", "8.07%", "32.44%")
)
# convert to numeric
campaigns <- campaigns %>% mutate(Open.Rate = as.numeric(gsub("%", "", as.character(Open.Rate))))
# plot
campaigns %>% ggplot(aes(x = as.numeric(Send.Time), y = Open.Rate), colour = "red") +
geom_line() +
scale_x_continuous(labels = campaigns$Send.Time, breaks = seq_along(campaigns$Send.Time)) +
geom_point() +
xlab("Session date")
Output:

Setting limits with scale_x_datetime and time data

I want to set bounds for the x-axis for a plot of time-series data which features only time (no dates). My limits are:
lims <- strptime(c("03:00","16:00"), format = "%H:%M")
And my ggplot prints fine, but when I add this to scale_x_datetime
scale_x_datetime(limits = lims)
I get Error: Invalid input: time_trans works with objects of class POSIXct only
Fully reproducible example courtesy of How to create a time scatterplot with R?
dates <- as.POSIXct(as.Date("2011/01/01") + sample(0:365, 100, replace=TRUE))
times <- as.POSIXct(runif(100, 0, 24*60*60), origin="2011/01/01")
df <- data.frame(
dates = dates,
times = times
)
lims <- strptime(c("04:00","16:00"), format = "%H:%M")
library(scales)
library(ggplot2)
ggplot(df, aes(x=dates, y=times)) +
geom_point() +
scale_y_datetime(limits = lims, breaks=date_breaks("4 hour"), labels=date_format("%H:%M")) +
theme(axis.text.x=element_text(angle=90))
the error message says that you should use as.POSIXct on lims.
You also need to add the date (year, month and day) in lims, because by default it will be `2015, which is off limits.
lims <- as.POSIXct(strptime(c("2011-01-01 03:00","2011-01-01 16:00"), format = "%Y-%m-%d %H:%M"))
ggplot(df, aes(x=dates, y=times)) +
geom_point() +
scale_y_datetime(limits =lims, breaks=date_breaks("4 hour"), labels=date_format("%H:%M"))+
theme(axis.text.x=element_text(angle=90))

Resources