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)
Related
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.
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=1:5,
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),
Mask=c(0,1,1,0,0))
df <- tidyr::pivot_longer(df, -1)
A tile plot is plotted as follows:
ggplot(df%>%filter(name!="Mask"),
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 = 15),
axis.title.x = element_text(size = 15),
plot.margin = margin(20, 20, 20, 20))
with the following output:
In ggplot, How it is possible to implement a texture by using the column Mask==1 in order to fill the Date?
Try the (not on CRAN) ggpattern-package
library(ggplot2)
#remotes::install_github("coolbutuseless/ggpattern")
library(ggpattern)
# set what cells need to be hatched
df <- df %>%
mutate(hatch = ifelse(Date %in% c(2,3), "yes", "no"))
ggplot(df%>%filter(name!="Mask"),
aes(x = Date, y = factor(name, levels = rev(unique(name))),
fill = as.factor(value), pattern = hatch)) +
geom_tile_pattern(pattern_color = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.025,
pattern_key_scale_factor = 0.5) +
geom_tile(color = "black", alpha = 0.5) +
scale_pattern_manual(values = c(yes = "stripe", no = "none")) +
scale_fill_manual(values = c("white", "grey50")) +
theme_void() +
theme(legend.position = "none",
axis.text = element_text(size = 15),
axis.title.x = element_text(size = 15),
plot.margin = margin(20, 20, 20, 20))
How to avoid overlapping the lagend labels in ggplot?
ggplot(g3, aes(variable, country, fill= value)) + geom_tile() +
theme(axis.text.y = element_text(size = 15), axis.text.x = element_text(angle = 45, hjust = 1, size = 15), legend.position="bottom", legend.text = element_text(size = 15, angle = 50),
axis.title.x = element_blank(),axis.title.y = element_blank())
For axis labels, the best way to fix this is to use the ggplot2::guide_axis() function, which will adjust both the angle and vertical/horizontal positioning at the same time. You can also make your legend labels easier to read by scaling the label. This might obviate the need to rotate the legend labels. For example:
library(ggplot2)
ggplot(g3, aes(variable, country, fill = value)) +
geom_tile() +
labs(x = "", y = "") +
scale_fill_continuous(labels = scales::label_number(scale = 10000, suffix = "k")) +
guides(x = guide_axis(angle = 45), fill = guide_colorbar(direction = "horizontal)) +
theme(legend.position = "bottom", text = element_text(size = 15))
I would like to change color and line type in my ggplot. I am using this code:
a <- runif(84, 20, 80)
a<-ts(a,start = 2009,frequency = 12)
#a<-ts(result$`dataset1$Summe`,start = 2009,frequency = 12)
a3 <- zoo(a, order.by = as.Date(yearmon(index(a))))
p1 <- autoplot(a3)
p1 + scale_x_date(labels = date_format("%m/%Y"),breaks = date_breaks("2 months"), limits = as.Date(c('2009-01-01','2017-08-01')))+ theme(axis.text.x = element_text(angle = 90))+ theme(axis.text.x = element_text(angle = 90))+
labs(x = "Date",y="Test") + theme(panel.background = element_rect(fill = 'white', colour = 'black'))+geom_line(linetype="dotted", color="red")
but only the color is changed. What should I do to change line type?
autoplot() will pick a sensible default for the object it's passed. If you want to customize its appearance it's probably better to use the standard ggplot() function.
To be able to do that the zoo object should be passed trough fortify():
ggplot(fortify(a3, melt = TRUE)) +
geom_line(aes(x = Index, y = Value), linetype='dashed', color="red") +
scale_x_date(labels = date_format("%m/%Y"),
breaks = date_breaks("2 months"),
limits = as.Date(c('2009-01-01','2017-08-01')))+
theme(axis.text.x = element_text(angle = 90),
axis.text.x = element_text(angle = 90),
panel.background = element_rect(fill = 'white', colour = 'black'))+
labs(x = "Date",y="Test")
(NB: the dashed line at the top is caused by the panel.background theme option)