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

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

Related

R ggplot2 - how to reverse y-axis having dates

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)))

For Loop for ggplot2 in R

I have this data frame where I want to create multiple plots at the same time in a loop, but when I run the code it gives me an error. Can anyone please tell me what I am doing wrong!
Data:
structure(list(Date = structure(c(289094400, 297043200, 304992000,
312854400, 320716800, 328665600), tzone = "UTC", class = c("POSIXct",
"POSIXt")), NORTH = c(4.06976744186047, 5.51675977653633, 7.2799470549305,
4.75015422578655, 4.59363957597172, 3.15315315315317), YORKSANDTHEHUMBER = c(4.0121120363361,
5.45851528384282, 9.52380952380951, 6.04914933837431, 3.03030303030299,
5.42099192618225), NORTHWEST = c(6.57894736842105, 6.95256660168939,
6.50060753341436, 5.5904164289789, 4.59211237169096, 4.70041322314051
), EASTMIDS = c(4.98489425981872, 8.20143884892085, 6.91489361702127,
5.22388059701494, 5.61465721040189, 4.64465584778958), WESTMIDS = c(4.65838509316771,
4.74777448071216, 8.66855524079319, 6.56934306569344, 3.22896281800389,
3.17535545023698), EASTANGLIA = c(6.74525212835624, 8.58895705521476,
8.47457627118643, 10.7291666666667, 4.8447789275635, 4.84522207267835
), OUTERSEAST = c(6.7110371602884, 7.53638253638255, 9.47317544707589,
8.56512141280351, 3.82269215128102, 2.11515863689776), OUTERMET = c(4.54545454545458,
6.58505698607005, 7.36633663366336, 7.08225746956843, 4.3747847054771,
1.68316831683168), LONDON = c(8.11719500480309, 10.3065304309196,
6.32299637535239, 7.65151515151515, 1.30190007037299, 2.1535255296978
), SOUTHWEST = c(6.17577197149644, 7.71812080536912, 7.63239875389407,
9.45489628557649, 2.46804759806079, 2.19354838709679), WALES = c(6.09418282548476,
8.35509138381203, 7.40963855421687, 7.01065619742007, 1.15303983228513,
3.47150259067357), SCOTLAND = c(5.15222482435597, 4.12026726057908,
5.40106951871658, 8.67579908675796, -0.280112044817908, 2.94943820224719
), NIRELAND = c(4.54545454545454, 4.94752623688156, 4.42857142857145,
2.96397628818967, 6.06731620903454, 0.0835073068893502), UK = c(5.76890543055322,
7.20302836425676, 7.39543442582184, 7.22885986848197, 3.23472252213347,
2.95766398929048)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
Code:
for (i in 2:ncol(data2)) { # Printing ggplot within for-loop
print(ggplot(data2, aes(x = Date, y = data2[, i])) + # Basic ggplot2 plot of x & y's
geom_line() +
labs(title = "Uk States",
y = "",
x = "") +
theme_bw() +
geom_hline(yintercept = 0))
Sys.sleep(1)
}
Error:
Don't know how to automatically pick scale for object of type tbl_df/tbl/data.frame. Defaulting to continuous.
Error in is.finite(x) : default method not implemented for type 'list'
I would suggest to loop over the column names instead of value. You may then use .data to use as y-index.
library(tidyverse)
for(i in names(data2)[-1]) { # Printing ggplot within for-loop
# Basic ggplot2 plot of x & y's
print(ggplot(data2, aes(x = Date, y = .data[[i]])) +
geom_line()+ labs(title = "Uk States",
y = "",
x = "")+
theme_bw()+
geom_hline(yintercept = 0))
Sys.sleep(1)
}
You may also try facet_wrap to combine multiple plots together.
data2 %>%
pivot_longer(cols = -Date) %>%
ggplot(aes(Date, value)) +
geom_line() + facet_wrap(~name) +
labs(title = "Uk States", x = "", y = "") +
theme_bw() +
geom_hline(yintercept = 0)
Another way of generating ggplot in a loop is to use lapply, where we loop for colnames and use aes_string as the aesthetic mapping.
Here the results are saved to the list ggplot_list, where you can extract individual plot by indexing (e.g. plot for NORTH is stored in ggplot_list[[1]])
Note that I've changed labs(title = i) so that the plot title would be your column names.
library(ggplot2)
ggplot_list <- lapply(colnames(data2[-1]), \(i) {
ggplot(data2, aes_string("Date", x)) +
geom_line() +
labs(title = i, y = "", x = "") +
theme_bw() +
geom_hline(yintercept = 0)
})

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)

ggplotly() does not display geom_vline / geom_hline when data is POSIXct

I am trying to make a graph with "time markers". These time markers are vertical lines for certain dates. Time data are POSIXct format. I would like to use the awesome interactive interface of Plotly and use my ggplot objects in it.
The problem is that these "time markers" doesn't show in after using ggplotly(). I ave already tried with plotly::add_segments() but it does not work.
Here are two reproductible examples :
1. With non-POSIXct data it works fine
# dummy dataset
df2 = data.frame(id = 1:10, measure = runif(10, 0, 20))
events2 = data.frame(number = c(2,3,8))
# ggplot graph
p2 = ggplot() + geom_line(data = df2, aes(x = id, y = measure)) +
geom_vline(data = events2, aes(xintercept = events2$number), color = "red")
p2
# plotly graph that displays the geom_vline properly
ggplotly(p2)
2. With POSIXct data is doesn't display the correct result
# dummy dataset
df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
"1 month"),
measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))
# ggplot graph
p = ggplot() + geom_line(data = df, aes(x = date, y = measure)) +
geom_vline(data = events, aes(xintercept = events$date), color = "red")
p
# plotly graph that does not display the geom_vline properly
ggplotly(p)
I have seen some workaround (like this one : Add vertical line to ggplotly plot) but it is "complicated". Is there a more simple way to solve this problem ?
I am using Windows 10 with R version 3.5.0, RStudio and the following packages :
library(tidyverse) and library(plotly)
A simple workaround is to set the xintecept of the geom_vline to numeric.
sample data
df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
"1 month"),
measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))
code
p = ggplot() + geom_line(data = df, aes(x = date, y = measure)) +
geom_vline(data = events, aes(xintercept = as.numeric(events$date)), color = "red")
result
ggplotly(p)

Need help on ggplot in R, I am getting an error: 'argument "x" is missing, with no default'

[enter image description here][1]I am trying to create a lowry plot in R but am having difficulty debugging the errors returned. I am using the following code to create the plot:
library(ggplot2)
library(reshape)
m_xylene_data <- data.frame(
Parameter = c(
"BW", "CRE", "DS", "KM", "MPY", "Pba", "Pfaa",
"Plia", "Prpda", "Pspda", "QCC", "QfaC", "QliC",
"QPC", "QspdC", "Rurine", "Vfac", "VliC", "Vmax"),
"Main Effect" = c(
1.03E-01, 9.91E-02, 9.18E-07, 3.42E-02, 9.27E-3, 2.82E-2, 2.58E-05,
1.37E-05, 5.73E-4, 2.76E-3, 6.77E-3, 8.67E-05, 1.30E-02,
1.19E-01, 4.75E-04, 5.25E-01, 2.07E-04, 1.73E-03, 1.08E-03),
Interaction = c(
1.49E-02, 1.43E-02, 1.25E-04, 6.84E-03, 3.25E-03, 7.67E-03, 8.34E-05,
1.17E-04, 2.04E-04, 7.64E-04, 2.84E-03, 8.72E-05, 2.37E-03,
2.61E-02, 6.68E-04, 4.57E-02, 1.32E-04, 6.96E-04, 6.55E-04
)
)
fortify_lowry_data <- function(data,
param_var = "Parameter",
main_var = "Main.Effect",
inter_var = "Interaction")
{
#Convert wide to long format
mdata <- melt(data, id.vars = param_var)
#Order columns by main effect and reorder parameter levels
o <- order(data[, main_var], decreasing = TRUE)
data <- data[o, ]
data[, param_var] <- factor(
data[, param_var], levels = data[, param_var]
)
#Force main effect, interaction to be numeric
data[, main_var] <- as.numeric(data[, main_var])
data[, inter_var] <- as.numeric(data[, inter_var])
#total effect is main effect + interaction
data$.total.effect <- rowSums(data[, c(main_var, inter_var)])
#Get cumulative totals for the ribbon
data$.cumulative.main.effect <- cumsum(data[, main_var])
data$.cumulative.total.effect <- cumsum(data$.total.effect)
#A quirk of ggplot2 means we need x coords of bars
data$.numeric.param <- as.numeric(data[, param_var])
#The other upper bound
#.maximum = 1 - main effects not included
data$.maximum <- c(1 - rev(cumsum(rev(data[, main_var])))[-1], 1)
data$.valid.ymax <- with(data,
pmin(.maximum, .cumulative.total.effect)
)
mdata[, param_var] <- factor(
mdata[, param_var], levels = data[, param_var]
)
list(data = data, mdata = mdata)
}
lowry_plot <- function(data,
param_var = "Parameter",
main_var = "Main.Effect",
inter_var = "Interaction",
x_lab = "Parameters",
y_lab = "Total Effects (= Main Effects + Interactions)",
ribbon_alpha = 0.5,
x_text_angle = 25)
{
#Fortify data and dump contents into plot function environment
data_list <- fortify_lowry_data(data, param_var, main_var, inter_var)
list2env(data_list, envir = sys.frame(sys.nframe()))
p <- ggplot(data) +
geom_bar(aes_string(x = param_var, y = "value", fill = "variable"),
data = mdata) +
geom_ribbon(
aes(x = .numeric.param, ymin = .cumulative.main.effect, ymax =
.valid.ymax),
data = data,
alpha = ribbon_alpha) +
xlab(x_lab) +
ylab(y_lab) +
scale_y_continuous(labels = "percent") +
theme(axis.text.x = text(angle = x_text_angle, hjust = 1)) +
scale_fill_grey(end = 0.5) +
theme(legend.position = "top",
legend.title =blank(),
legend.direction = "horizontal"
)
p
}
m_xylene_lowry <- lowry_plot(m_xylene_data)
When I run the code, it is giving me the following error:
Error: argument "x" is missing, with no default
It is not specific enough for me to know what the issue is. What is causing the error to be displayed and how can I make error statements more verbose?
Lowry PLOT
It seems that you have more than one faulty element in your code than just the error it throws. In my experience it always helps to first check whether the code works as expected before putting it into a function. The plotting-part below should work:
p <- ggplot(data) + # no need to give data here, if you overwrite it anyway blow, but does not affect outcome...
# geom_bar does the counting but does not take y-value. Use geom_col:
geom_col(aes_string(x = param_var, y = "value", fill = "variable"),
data = mdata,
position = position_stack(reverse = TRUE)) +
geom_ribbon(
aes(x = .numeric.param, ymin = .cumulative.main.effect, ymax =
.valid.ymax),
data = data,
alpha = ribbon_alpha) +
xlab(x_lab) +
ylab(y_lab) +
# use scales::percent_format():
scale_y_continuous(labels = scales::percent_format()) +
# text is not an element you can use here, use element_text():
theme(axis.text.x = element_text(angle = x_text_angle, hjust = 1)) +
scale_fill_grey(end = 0.5) +
# use element_blank(), not just blank()
theme(legend.position = "top",
legend.title = element_blank(),
legend.direction = "horizontal"
)
This at least plots something, but I'm not sure whether it is what you expect it to do. It would help if you could show the desired output.
Edit:
Added position = position_stack(reverse = TRUE) to order according to sample plot.

Resources