limits argument in scale_x_date (ggplot) still produces dates outside data.frame range
That's normal, as the argument you look for is not limits
but expand
, as that's the one adding a little extra space left and right of the limits. You don't have to specify the limits at all, as the minimum and maximum are used by default.
So this code gives you the plot you're after:
ggplot(data=df, aes(x=date, y=value)) +
geom_line() +
scale_x_date(date_breaks = "day", expand = c(0,0)) +
theme(axis.text.x=element_text(angle=90, vjust = 0.5))
From the help page:
expand : A numeric vector of length two giving multiplicative and
additive expansion constants. These constants ensure that the data is
placed some distance away from the axes. The defaults are c(0.05, 0)
for continuous variables, and c(0, 0.6) for discrete variables.
This gives
Using ggplot scale_x_datetime() to set first date on x axis
library(ggplot2)
dat <- data.frame(date = seq(as.Date("2020-03-05 17:00:00",
format = "%Y-%m-%d %H:%M:%S"),
as.Date("2022-03-05 17:00:00",
format = "%Y-%m-%d %H:%M:%S"),
length=18000))
dat$x <- rnorm(18000)
dat$date <- as.POSIXct(dat$date)
ggplot(dat, aes(x=date, y=x)) +
geom_line() +
theme_classic() +
scale_x_datetime(breaks= seq(min(dat$date), max(dat$date), length=6),
date_labels="%b-%y")
Created on 2022-05-03 by the reprex package (v2.0.1)
Breaks for scale_x_date in ggplot2 and R
One approach would be to treat the x-axis as numeric and set the breaks and labels aesthetics with scale_x_continuous()
.
ggplot(my.data, aes(as.numeric(date), vals)) +
geom_line(size = 1.5) +
scale_x_continuous(breaks = as.numeric(my.data$date)
, labels = format(my.data$date, format = "%m/%d"))
though the break between 7/24 through 7/28 looks a bit strange in my opinion. However, I think that's what you want? Let me know if I've misinterpreted.
EDIT
As noted above, I wasn't thrilled with the way the breaks looked above, specifically with the gray grid in the background. Here's one way to maintain the rectangular grid and to only label the points where we have data. You could do this all within the ggplot call, but I think it's easier to do the processing outside of ggplot. First, create a vector that contains the sequence of numbers corresponding to the dates. Then we'll update the appropriate labels and replace the NA entries with " "
to prevent anything from being plotted on the x-axis for those entries:
xscale <- data.frame(breaks = seq(min(as.numeric(my.data$date)), max(as.numeric(my.data$date)))
, labels = NA)
xscale$labels[xscale$breaks %in% as.numeric(my.data$date)] <- format(my.data$date, format = "%m/%d")
xscale$labels[is.na(xscale$labels)] <- " "
This gives us something that looks like:
breaks labels
1 15177 07/22
2 15178 07/23
3 15179 07/24
4 15180
5 15181
6 15182
7 15183 07/28
8 15184 07/29
which can then be passed to the scale like this:
scale_x_continuous(breaks = xscale$breaks, labels = xscale$labels)
ggplot: date axis. How to set limits?
Maybe this is what you are looking for. Via the limits you set the range of the data. However, you have to keep in mind that ggplot2 by default expands a continuous axis by 5 percent on each side. The amount of expansion can be set via the expand
argument. Additionally, if you want a specific start and/or end age then I would suggest to set the breaks via the breaks
arguement instead of using date_breaks
:
library(lubridate)
library(ggplot2)
library(tibble)
set.seed(42)
tibble(
date = ymd("2019/12/31") + 1:366,
value = rnorm(1:366)) %>%
ggplot(aes(date, value)) +
geom_line() +
scale_x_date("Day", breaks = seq(ymd("2020/01/01"), ymd("2020/12/31"), by = "10 days"), date_labels = "%b %d",
limits = ymd(c("2020/01/01", "2020/12/31")),
expand = c(0, 0)) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
R:ggplot and for loop ,scale_x_date overwrites one before
It seems you want to plot 6 year periods of a time-series beneath each other. If you use facet_wrap
upon a previously computed factor of timespans the code reduces to a few lines:
library(ggplot2)
library(scales)
library(xts)
set.seed(123)
sunt <- as.xts(rnorm(10958), seq(as.Date("1984-01-01"), as.Date("2014-01-01")-1,by="days"))
names(sunt) <- "Tokyo"
# Divide the time-series into 6 year periods
sunt$period <- cut(x = time(sunt), breaks = "6 years")
ggplot(sunt, aes(x = index(sunt), y = Tokyo)) + xlab("") + ylab("") + geom_line() +
scale_x_date(labels = date_format("%Y/%m/%d")) +
facet_wrap(~period, scales = "free_x", ncol = 1) +
theme(strip.background = element_blank(), strip.text = element_blank())
If you use cut
to segment the time-series you benefit from the fact that it accounts for leap years, something that you seem to miss (there are 8 leap years between 1984 and 2014).
How to set date axis limits in ggplot2?
ggplot2
expands the axes. You can prevent the expansion of the x-axis by setting expand = c(0,0)
in scale_x_date
.
However this can undesirably cut the labels. Maybe a better option is to give the breaks by setting
breaks = seq(as.Date("01/03/2018", '%d/%m/%Y'), as.Date("01/01/2020", '%d/%m/%Y'), by = "month")
in scale_x_date
, instead of date_breaks = "1 month"
.
Annotate first month with year in ggplot2
You can do it with a custom date formatter to remove duplicated years:
my_date_format <- function()
{
function(x)
{
m <- format(x,"%b")
y <- format(x,"%Y")
ifelse(duplicated(y),m,paste(m,y))
}
}
ggplot(DF, aes(x=date, y=y)) +
geom_point() +
scale_x_date(breaks = "1 month", minor_breaks = "1 week", labels=my_date_format())
Hiding tick marks and tick labels of minimum and maximum limits of axes for base R plots
There are a couple of options. First, you generally want to drop the default axis labels using xaxt='n'
or yaxt='n'
. Next, you could manually specify the locations of the tick marks in axis()
or use the pretty()
function with dropping the first and last values (used head
and tail
in example) to get some nice tick mark locations. It might require some manual fine tuning.
x <- c(1, 2, 3)
xlabs <- c("A", "B", "C")
y <- c(4, 5, 6)
barplot(x,
xlab = "X",
names.arg = xlabs,
ylim = c(0, 3),
ylab = "Y",
yaxt='n' # drops the y axis and tick marks
)
# draw a vertical line that will cover the whole vertical axis, if desired
abline(v=par('usr')[1],lwd=2)
# pretty will give nice tickmark locations, and head and tail drop first and last
# add the 0 to x vector because barplot starts at 0
axis(side=2,tail(pretty(c(0,x)),-1))
plot(x, y,
xlim = c(1, 3),
xlab = "X",
ylim = c(4, 6),
ylab = "Y",
xaxt='n', # no default x axis with ticks
yaxt='n' # no default y axis with ticks
)
# add tickmark and axis locations manually for each axis
# using the pretty function for where the tick marks normally would be, then head and tail to drop first and last
axis(side=1,tail(head(pretty(c(x)),-1),-1))
axis(side=2,tail(head(pretty(c(y)),-1),-1))
Related Topics
Finding Overlaps Between Interval Sets/Efficient Overlap Joins
Split Text String in a Data.Table Columns
Ggplot2 Multiple Sub Groups of a Bar Chart
Remove Ids That Occur X Times R
Why Is Apply() Method Slower Than a for Loop in R
Select Values from Different Columns Based on a Variable Containing Column Names
Overlay Data Onto Background Image
Convert Yyyymmdd String to Date Class in R
Linear Regression Loop for Each Independent Variable Individually Against Dependent
How to Round Up to the Nearest 10 (Or 100 or X)
Converting Two Columns of a Data Frame to a Named Vector
R Compare Multiple Values with Vector and Return Vector
How to Calculate Combination and Permutation in R
How to Draw Stacked Bars in Ggplot2 That Show Percentages Based on Group