R ggplot2 - how to reverse y-axis having dates - r

In continuation with the ask from #David, I'm unable to reverse the y-axis having date field.
I tried to reproduce the reprex - solution given by #Marcelo and #Oliver, but it is also throwing an error as below:
Error: Invalid input: time_trans works with objects of class POSIXct only
I have executed the same code as mentioned in the below link:
Reverse datetime (POSIXct data) axis in ggplot
Can somebody help to understand why we get this error? or is it because of any version issues in my system??
ggplot2 version 3.4.0
R version 4.2.2
I tried the same code as below:
MyData <-
structure(list(Date = structure(c(1492979809.99827, 1492602845.68722,
1493093428.90318, 1492605578.0691, 1492961342.65056, 1492771976.83545,
1493020588.88485, 1493057018.85104, 1492852011.23873, 1492855996.55059
), class = c("POSIXct", "POSIXt")), Value = c(4.52885504579172,
6.0024610790424, 8.96430060034618, 7.06435370026156, 5.08460514713079,
3.47828012891114, 6.29844291834161, 0.898315710946918, 1.44857675535604,
5.74641009094194)), .Names = c("Date", "Value"), row.names = c(NA,
-10L), class = "data.frame")
library(ggplot2)
library(scales)
c_trans <- function(a, b, breaks = b$breaks, format = b$format) {
a <- as.trans(a)
b <- as.trans(b)
name <- paste(a$name, b$name, sep = "-")
trans <- function(x) a$trans(b$trans(x))
inv <- function(x) b$inverse(a$inverse(x))
trans_new(name, trans, inverse = inv, breaks = breaks, format=format)
}
rev_date <- c_trans("reverse", "time")
ggplot(MyData, aes(x=Value, y=Date)) +
geom_point() +
scale_y_continuous(trans = rev_date)
Getting the error as below
Error: Invalid input: time_trans works with objects of class POSIXct only

I think creating a transformer is overkill here. You could simply make the date-time a numeric variable, and use as.POSIXct as a labelling function inside scale_y_reverse:
ggplot(MyData, aes(Value, as.numeric(Date))) +
geom_point() +
scale_y_reverse("Date", labels = ~as.POSIXct(.x, origin = "1970-01-01"),
breaks = as.numeric(seq(as.POSIXct("2017-04-19"), by = "day",
length = 7)))

Related

Reverse datetime (POSIXct data) axis in ggplot previous solution broken

A previous post detailed a solution to reversing the time on a ggplot post with this data:
MyData <-
structure(list(Date = structure(c(1492979809.99827, 1492602845.68722,
1493093428.90318, 1492605578.0691, 1492961342.65056, 1492771976.83545,
1493020588.88485, 1493057018.85104, 1492852011.23873, 1492855996.55059
), class = c("POSIXct", "POSIXt")), Value = c(4.52885504579172,
6.0024610790424, 8.96430060034618, 7.06435370026156, 5.08460514713079,
3.47828012891114, 6.29844291834161, 0.898315710946918, 1.44857675535604,
5.74641009094194)), .Names = c("Date", "Value"), row.names = c(NA,
-10L), class = "data.frame")
and this solution:
c_trans <- function(a, b, breaks = b$breaks, format = b$format) {
a <- as.trans(a)
b <- as.trans(b)
name <- paste(a$name, b$name, sep = "-")
trans <- function(x) a$trans(b$trans(x))
inv <- function(x) b$inverse(a$inverse(x))
trans_new(name, trans, inverse = inv, breaks = breaks, format=format)
}
rev_date <- c_trans("reverse", "time")
ggplot(MyData, aes(x=Value, y=Date)) +
geom_point() +
scale_y_continuous(trans = rev_date)
However, when I try and run this code now I get the following error:
Error: Invalid input: time_trans works with objects of class POSIXct only
I am running this code on R version 4.2.2 and cannot find a solution to fix this.
I tried forcing my data into POSIXct format, but the graphing still breaks in the same way.
You could slightly modify the function coord_x_datetime from the tidyquant package to reverse the datetime for your y-axis. Here is the function called coord_y_datetime:
coord_y_datetime <- function(xlim = NULL, ylim = NULL, expand = TRUE) {
if (!is.null(ylim)) {
ylim <- lubridate::as_datetime(ylim)
}
ggplot2::coord_cartesian(xlim = xlim, ylim = ylim, expand = expand)
}
Here is a reproducible example:
library(ggplot2)
ggplot(MyData, aes(x = Value, y = Date)) +
geom_point() +
coord_y_datetime(ylim = c(max(MyData$Date), min(MyData$Date)))
Created on 2022-11-14 with reprex v2.0.2

R geom_forecast object not found

I want to create a forecasting plot via ggplot2. So, I have been trying to follow this example, however the desired output is not as intended, as I would like to have year on x-axis and AvgTMean on the y-axis`.
Purpose is the forecast the next 10 years.
How can I do this?
Data (AvgTMaxYear):
structure(list(year = 1980:2021, AvgTMean = c(24.2700686838937,
23.8852956598276, 25.094446596092, 24.1561175050287, 24.157183605977,
24.3047482638362, 24.7899738481466, 24.5756232655603, 24.5833086228592,
24.7344695534483, 25.3094451071121, 25.2100615173707, 24.3651692293534,
24.5423890611494, 25.2492166633908, 24.7005097837931, 24.2491591827443,
25.0912281781322, 25.0779264303305, 24.403294248319, 24.4983991453592,
24.4292324356466, 24.8179824927011, 24.7243948463075, 24.5086534543966,
24.2818632071983, 24.4567195220259, 24.8402224356034, 24.6574465515086,
24.5440715673563, 23.482670620977, 24.9979594684914, 24.5452453980747,
24.9271462811494, 24.7443215819253, 25.8929839790805, 25.1801908261063,
25.2079308058908, 25.0722425561207, 25.4554644289799, 25.4548979078736,
25.0756772250287)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-42L))
Method 1:
library(tidyverse)
library(forecast)
# Convert to timeseries object
AvgTMaxYearTS = ts(AvgTMaxYear)
# Plot
autoplot(AvgTMaxYearTS) + geom_forecast()
Output:
Method 2:
# Using fortify.ts
p = ggplot(aes(x = year, y = AvgTMean), data = AvgTMaxYear)
p = p + geom_line()
p + geom_forecast()
Error:
Error in FUN(X[[i]], ...) : object 'AvgTMean' not found
When I run your second method it runs like this:
library(ggplot2)
library(forecast)
p = ggplot(aes(x = year, y = AvgTMean), data = AvgTMaxYear)
p = p + geom_line()
p + geom_forecast()
Output:

Setting time limits on axis removes all values

I have this simple data:
structure(list(ID = 1:2, timing = structure(c(1654641111.14,
1654640774.523), tzone = "CET", class = c("POSIXct", "POSIXt"))), class = "data.frame", row.names = c(NA,
-2L))
ID timing
1 1 2022-06-08 00:31:51.140
2 2 2022-06-08 00:26:14.523
When I plot using ggplot2, I get this:
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point()
But when I set limits, the graph is empty:
lims <- as.POSIXct(strptime(c("35:00", "25:00"),
format = "%M:%OS",
tz = "CET"))
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point() +
scale_y_datetime(limits = lims)
Warning message:
Removed 2 rows containing missing values (geom_point).
I tried to find any solution, but I can't figure out why the limits remove all my values. Does anyone have a solution?
This is simply due to your limits being round the wrong way (they should be earliest, latest whereas you have latest, earliest).
So you can do:
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point() +
scale_y_datetime(limits = rev(lims))

Plot multiple time-series in a single graph - Error: Invalid input: date_trans works with objects of class Date only

I am trying to plot multiple time series into a single graph like the attached image, but I am getting this error Error: Invalid input: date_trans works with objects of class Date only. I tried to solve the issue by converting the column containing the Months into a date format either using the lubricate package, or other methods I found on internet. Here is the data:
structure(list(Month = c("2016-01-01", "2016-02-01", "2016-03-01",
"2016-04-01", "2016-05-01", "2016-10-01", "2016-11-01", "2016-12-01"
), Residential = c(36.22021, 40.31832, 37.83721, 39.75821, 34.7028,
42.97021, 37.61029, 41.58934), Residential.Informal = c(33.3279,
35.2452, 34.67857, 30.44121, 30.65073, 35.55425, 34.04282, 35.22392
), Non.Residential = c(79.75459, 80.79518, 96.62088, 95.32751,
94.49208, 91.24384, 115.131, 119.9929)), class = "data.frame", row.names = c(NA,
-8L))
here is the code, without all my try-and-error in it:
df <- read.csv("wd/ts_all_month.csv")
df_melt = melt(df, id.vars = 'Month')
#multiple ts plots
tiff("ts_lu.tiff", units="in", width=14, height=8, res=300)
ggplot(df_melt, aes(x = Month, y = value)) +
geom_line() +
facet_wrap(~ variable, scales = 'free_y', ncol = 1)
dev.off()
With your sample data you can do:
ggplot(df_melt, aes(x = Month, y = value)) +
geom_line() +
facet_wrap(~ variable, scales = 'free_y', ncol = 1)

R ggplot2: colouring step plot depending on value

How do I configure a ggplot2 step plot so that when the value being plotted is over a certain level it is one colour and when it is below that certain level it is another colour? (Ultimately I would like to specify the colours used.)
My first thought was that this would be a simple issue that only required me to add a column to my existing data frame and map this column to the aes() for geom_step(). That works to a point: I get two colours, but they overlap as shown in this image:
I have searched SO for the past several hours and found many similar but not identical questions. However, despite trying a wide variety of combinations in different layers I have not been able to resolve the problem. Code follows. Any help much appreciated.
require(ggplot2)
tmp <- structure(list(date = structure(c(1325635200, 1325635800, 1325636400,
1325637000, 1325637600, 1325638200, 1325638800, 1325639400, 1325640000,
1325640600, 1325641200, 1325641800, 1325642400, 1325643000, 1325643600,
1325644200, 1325647800, 1325648400, 1325649000, 1325649600, 1325650200,
1325650800, 1325651400, 1325652000, 1325652600, 1325653200, 1325653800,
1325654400, 1325655000, 1325655600, 1325656200, 1325656800), tzone = "", tclass = c("POSIXct",
"POSIXt"), class = c("POSIXct", "POSIXt")), Close = c(739.07,
739.86, 740.41, 741.21, 740.99, 741.69, 742.64, 741.34, 741.28,
741.69, 741.6, 741.32, 741.95, 741.86, 741.02, 741.08, 742.08,
742.88, 743.19, 743.18, 743.78, 743.65, 743.66, 742.78, 743.34,
742.81, 743.31, 743.81, 742.91, 743.09, 742.47, 742.99)), .Names = c("date",
"Close"), row.names = c(NA, -32L), class = "data.frame")
prevclose <- 743
tmp$status <- as.factor(ifelse (tmp$Close> prevclose, "Above", "Below"))
ggplot() +
geom_step(data = tmp,aes(date, Close, colour = status))
You need group = 1 in aes:
# top panel
ggplot(tmp, aes(date, Close, colour = status, group = 1)) +
geom_step() + scale_colour_manual(values = c("pink", "green"))
Maybe you want to do something like this:
# make sure that data is sorted by date
tmp2 <- arrange(tmp, date)
# add intermittent column between below/above
tmp3 <- tmp2[1, ]
for (i in seq(nrow(tmp2))[-1]) {
if (tmp2[i-1, ]$status != tmp2[i, ]$status) {
tmp3 <- rbind(tmp3,
transform(tmp2[i, ], Close = prevclose, status = tmp2[i-1, ]$status),
transform(tmp2[i, ], Close = prevclose))
}
tmp3 <- rbind(tmp3, tmp2[i, ])
}
# bottom panel
ggplot(tmp3, aes(date, Close, colour = status, group = 1)) + geom_step() +
scale_colour_manual(values = c("pink", "green"))

Resources