I am making a time series figure in ggplot2 and would like to set limits for the x-axis. When I try to set the limits using scale_x_datetime(limits = ...), dates beyond the limits are shown, how can I avoid this? I have tried using answers found in similar SO questions (similar 1, similar 2) but have not had success.
Example Data:
library(ggplot2)
library(lubridate)
df <- data.frame(matrix(ncol = 2, nrow = 70176))
colnames(df)[1:2] <- c("DateTime","Value")
df$DateTime <- seq(ymd_hm('2020-01-01 00:00'),ymd_hm('2021-12-31 23:45'), by = '15 mins')
df$Value <- rnorm(70176,100,20)
This attempt comes from the first similar SO question
lims <- as.POSIXct(strptime(c("2020-01-01 00:00","2021-12-31 23:45"), format = "%Y-%m-%d %H:%M"))
ggplot(df, aes(x = DateTime, y = Value)) +
geom_line() +
scale_x_datetime(date_labels = "%b %d %Y",
date_breaks = "1 month",
limits = lims) +
labs(x = "",
y = "Value") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16, color = "black"),
axis.text.x = element_text(size = 16, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 16, color = 'black'))
This attempt comes from the second similar SO question
ggplot(df, aes(x = DateTime, y = Value)) +
geom_line() +
scale_x_datetime(date_labels = "%b %d %Y",
date_breaks = "1 month",
limits = c(min(df$DateTime), max(df$DateTime))) +
labs(x = "",
y = "Value") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16, color = "black"),
axis.text.x = element_text(size = 16, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 16, color = 'black'))
The ideal figure would not display dates outside of the limits of the data (i.e., Dec 2019 or Jan 2022).
#JonSpring suggestion of using scale_x_datetime(..., expand = expansion(add = c(0,0))) answered my question. Below is the code using the example dataset for others who might come across this question.
lims <- as.POSIXct(strptime(c("2019-12-15 00:00","2022-01-15 23:45"), format = "%Y-%m-%d %H:%M"))
ggplot(df, aes(x = DateTime, y = Value)) +
geom_line() +
scale_x_datetime(date_labels = "%b %d %Y",
date_breaks = "1 month",
limits = lims,
expand = expansion(add = c(0,0))) +
labs(x = "",
y = "Value") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16, color = "black"),
axis.text.x = element_text(size = 16, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 16, color = 'black'))
Using expand = c(0,0) in scale_x_datetime() will remove extra space.
Related
I'm new to r and tried the hourly heatmapt from the r grah gallery:
https://r-graph-gallery.com/283-the-hourly-heatmap.html
My question is, if it possible to adjust it that way, that the x axis ish shown with the correct amount of days in the month(example: Jan 1 … 31, Feb 1 … 28)
I tried to change scale_x_continuos with scale_x_date but it didnt worked as expected.
You can amend the code as folows, using a custom labelling function in scale_x_continuous:
ggplot(df, aes(day, hour, fill = temp)) +
geom_tile(color = "white",size = 0.1) +
scale_fill_viridis(name = "Hrly Temps C", option = "C") +
facet_grid(year~month, scales = 'free_x') +
scale_y_continuous(trans = "reverse", breaks = unique(df$hour)) +
scale_x_continuous(breaks = ~c(1, 10, 20, floor(max(.x, na.rm = TRUE)) -2)) +
theme_minimal(base_size = 8) +
labs(title= paste("Hourly Temps - Station", statno), x = "Day",
y = "Hour Commencing") +
theme(legend.position = "bottom",
plot.title = element_text(size = 14, hjust = 0),
axis.text.y = element_text(size = 6),
strip.background = element_rect(colour = "white"),
axis.ticks = element_blank(),
axis.text = element_text(size = 7),
legend.title = element_text(size = 8),
legend.text = element_text(size = 6)) +
removeGrid()
I have a really long y-axis title with scientific notation that I want to wrap and make center aligned. I can either wrap the title and have it left aligned, or center an incorrect format of the title. How can I wrap the axis title AND have it centered in ggplot2?
Example Data
set.seed(321)
df <- data.frame(matrix(ncol = 2, nrow = 3))
colnames(df)[1:2] <- c("date","value")
df$value <- round(rnorm(3, 100,30),0)
st <- as.Date("2020-01-01")
en <- as.Date("2020-03-31")
df$date <- seq.Date(st,en,by = '1 month')
This makes the ggplot2 figure with the unwrapped long y-axis title
library(ggplot2)
ggplot(df, aes(x = date, y = value)) +
geom_point() +
labs(x = "",
y = expression(paste("Here is a really really really looooonnnng title with notation ( ", m^-2,")"))) +
scale_x_date(breaks = seq(st, en, by = "1 month"),
limits = c(st,en),
date_labels = "%b %Y") +
scale_y_continuous(limits = c(0,150),
breaks=seq(0,150,25)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
I have tried using \n which wraps the title but, the title is not centered, it is left aligned
ggplot(df, aes(x = date, y = value)) +
geom_point() +
labs(x = "",
y = expression(paste("Here is a really really really \n looooonnnng title with notation ( ", m^-2,")"))) +
scale_x_date(breaks = seq(st, en, by = "1 month"),
limits = c(st,en),
date_labels = "%b %Y") +
scale_y_continuous(limits = c(0,150),
breaks=seq(0,150,25)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
Using str_wrap() centers the title but the title is no longer formatted correctly
library(stringr)
ggplot(df, aes(x = date, y = value)) +
geom_point() +
labs(x = "",
y = str_wrap(
expression(paste("Here is a really really really \n looooonnnng title with notation ( ", m^-2,")")),50)
)+
scale_x_date(breaks = seq(st, en, by = "1 month"),
limits = c(st,en),
date_labels = "%b %Y") +
scale_y_continuous(limits = c(0,150),
breaks=seq(0,150,25)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
I tried creating a wrapper function based on this similar SO question but it also did not format the title correctly
wrapper <- function(x, ...)
{
paste(strwrap(x, ...), collapse = "\n")
}
my_title = expression(paste("Here is a really really really looooonnnng title with notation ( ", m^-2,")"))
ggplot(df, aes(x = date, y = value)) +
geom_point() +
labs(x = "",
y = wrapper(my_title, 50)) +
scale_x_date(breaks = seq(st, en, by = "1 month"),
limits = c(st,en),
date_labels = "%b %Y") +
scale_y_continuous(limits = c(0,150),
breaks=seq(0,150,25)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
You can try to use the package ggtext. If we want to use it, we need to change the normal expression style to HTML and CSS style (which is <sup></sup> for superscript).
For clearer code, I've put your y-axis title into a variable y_lab. The code that is doing the job is theme(axis.title.y = element_textbox_simple(orientation = "left-rotated", halign = 0.5)).
library(ggplot2)
library(ggtext)
y_lab <- "Here is a really really really looooonnnng<br>title with notation (m<sup> -2</sup>)"
ggplot(df, aes(x = date, y = value)) +
geom_point() +
labs(x = "",
y = y_lab)+
scale_x_date(breaks = seq(st, en, by = "1 month"),
limits = c(st,en),
date_labels = "%b %Y") +
scale_y_continuous(limits = c(0,150),
breaks=seq(0,150,25)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"),
axis.title.y = element_textbox_simple(orientation = "left-rotated", halign = 0.5))
I cannot get geom_boxplot to display a time series from oldest date to newest date.
Example Data:
set.seed(321)
dat <- data.frame(matrix(ncol = 3, nrow = 216))
colnames(dat)[1:3] <- c("Date","Location","Value")
dat$Value <- round(rnorm(216, 100,75),0)
dat$Location <- rep(c("Location 1","Location 2"), each = 108)
st <- as.Date("2020-01-01")
en <- as.Date("2022-12-31")
dat$Date <- rep(seq.Date(st,en,by = '1 month'),6)
str(dat)
This plot has the x-axis sorted based on the alphabetical order of the month, then year (i.e., Apr 2020, Apr 2021, Apr 2022, Aug 2020, etc).
ggplot(dat, aes(x = format(Date, "%b %Y"), y = Value, fill = Location, group = interaction(Date, Location))) +
geom_boxplot() +
labs(x = "") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
How can I get the x-axis to display in chronological order (i.e., Jan 2020, Feb 2020, etc.)?
We could do it this way:
library(ggplot2)
ggplot(dat, aes(x = Date, y = Value, fill = Location, group = interaction(Date, Location))) +
geom_boxplot() +
labs(x = "") +
scale_x_date(date_breaks = "1 month",
date_labels = "%b %Y") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
For ggplot2 to arrange your data by Date, it's simplest to preserve the x axis data as Date data (which ggplot2 knows how to display on a timeline) instead of as formatted text (which ggplot2 doesn't assign any semantic meaning to -- "Jan 2020" is no different from "Apple"). You can adjust the label formatting with scale_x_date(date_labels = ...)
(It's also possible to sort text values by converting them to "factors," which have the option of being ordered, but then you would lose the relationship to the timeline; gaps in time would not be shown with gaps, for instance.)
library(ggplot2)
ggplot(dat, aes(x = Date, y = Value, fill = Location, group = interaction(Date, Location))) +
geom_boxplot() +
scale_x_date(date_labels = "%b %Y") +
labs(x = "") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"))
From the following dataframe df:
df <- data.frame(Date=as.POSIXct(c("2002-07-01","2002-06-01","2002-05-01","2002-04-01","2002-03-01")),
Cat1=c(1,0,1,0,0),
Cat2=c(1,1,1,0,0),
Cat3=c(0,1,1,0,1),
Cat4=c(0,0,1,1,0))
df <- tidyr::pivot_longer(df, -1)
When using scale_x_datetime this require POSIXct class object, otherwise this complaints with error.
Error: Invalid input: time_trans works with objects of class POSIXct
only
ggplot(df,
aes(x = Date, y = factor(name, levels = rev(unique(name))),
fill = as.factor(value))) +
geom_tile(color = "black") +
scale_fill_manual(values = c("white", "grey50")) +
theme_void() +
theme(legend.position = "none",
axis.text = element_text(size = 8),
plot.margin = margin(20, 20, 20, 20),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size =5))+
scale_x_datetime(date_breaks = "1 month",
labels = scales::date_format("%m-%Y"))
With the following input:
By inspecting the range of Date column, this does not match with plot labels from x-axis.
range(df$Date)
Does anyone how to solve this?
Use date class, and scale_x_date
library(ggplot2)
# changing the class by constructing your data differently
df <- data.frame(Date=as.Date(c("2002-07-01","2002-06-01","2002-05-01","2002-04-01","2002-03-01")),
Cat1=c(1,0,1,0,0),
Cat2=c(1,1,1,0,0),
Cat3=c(0,1,1,0,1),
Cat4=c(0,0,1,1,0))
df <- tidyr::pivot_longer(df, -1)
ggplot(df,
aes(x = Date, y = factor(name, levels = rev(unique(name))),
fill = as.factor(value))) +
geom_tile(color = "black") +
scale_fill_manual(values = c("white", "grey50")) +
theme_void() +
theme(legend.position = "none",
axis.text = element_text(size = 8),
plot.margin = margin(20, 20, 20, 20),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size =5))+
scale_x_date(labels = scales::date_format("%m-%Y"))
Created on 2021-11-02 by the reprex package (v2.0.1)
I am developing a Taipan Chart that would show date variations to different items.
I got completely stuck to sort out the data by the Reporting date order to have the line ( geom_path() ) connecting the points in that order.
I was trying to sort it as you can see in the code. However, nothing is happening.
Could you please help me with this issue? Data Link .csv : https://drive.google.com/file/d/1MUJn4zPNIkZu1bEq_qNdConVLsDeebzv/view
library(ggplot2)
library(scales)
x <- as.Date(dataset$"Due Date", "%Y-%m-%d")
y <- as.Date(dataset$"Reporting Date", "%Y-%m-%d")
Item <- dataset$"Key Work Activity / Milestone"
ggplot(dataset[order(dataset$"Reporting Date"),], aes (x,y,colour = factor(Item))) +
geom_path(size = 1) +
labs( x = "Forecast Date", y = "Reporting Date") +
theme(
legend.position = "bottom",
panel.background = element_rect(fill=NA, colour = NA),
panel.grid.major = element_line (size = 0.1, linetype = "solid", colour = "black")
)+
geom_point(size=3) +
geom_hline(yintercept = Sys.Date(), linetype = "dashed" , colour ="blue") +
geom_vline(xintercept = Sys.Date(), linetype = "dashed", colour = "blue") +
scale_x_date(date_labels = "%b %Y", date_breaks = "1 month") +
theme(axis.text.x = element_text(angle = 45)) +
scale_y_date(date_labels = "%b %Y", date_breaks = "1 month") +
theme(axis.text.y = element_text(angle = 45))
This is what I am trying to achieve
This is what I have now