ggplot generates jagged/broken lines in specific cases - r

I recently encountered several cases where the ggplot produced jagged lines. In the following example, I generate dense time-course data with the package fda and draw two line plots. The first plot gives the black line and the other plot displays the same line except that we use different colors to denote the signs of the values. In the end, I export the plots as eps files and open them in Adobe Illustrator.
# install.packages("fda")
# dir.create("tmp")
library(dplyr)
library(tidyr)
library(ggplot2)
library(fda)
times_sparse <- seq(0, 10, 0.5)
times <- seq(0, 10, 0.02)
basis <- create.bspline.basis(
rangeval = c(0, 10), norder = 4,
breaks = times_sparse
)
nbasis <- basis$nbasis
set.seed(2501)
coeff <- rnorm(nbasis, sd = 0.1)
y <- eval.fd(times, fd(coeff, basis)) |> as.numeric()
dat <- data.frame(t = times, y = y) |>
mutate(pos = factor((y > 0) * 1, levels = c(1, 0)))
### first plot: 1 colors, smooth lines
ggplot(dat) +
geom_line(aes(x = t, y = y)) +
theme_bw() +
theme(panel.grid = element_blank())
# ggsave("tmp/line1a.eps", device = "eps",
# width = 6, height = 6)
### second plot: 2 colors, jagged lines
ggplot(dat) +
geom_line(aes(x = t, y = y, color = pos, group = 1)) +
theme_bw() +
theme(panel.grid = element_blank())
# ggsave("tmp/line1b.eps", device = "eps",
# width = 6, height = 6)
In the screenshots which display the zoomed-in line, we observe that the line in the first plot is smooth, while the line in the second plot is jagged. How can I fix the problem?
Here's my system info:
# R version 4.1.1 (2021-08-10)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# Running under: Windows 10 x64 (build 22000)
Note: My goal is to generate an eps/pdf file of something like the second plot from R. Other methods that achieve the same goal are appreciated.

You should add lineend = "round" to your geom_line
ggplot(dat) +
geom_line(aes(x = t, y = y, color = pos, group = 1), lineend = "round") +
theme_bw() +
theme(panel.grid = element_blank())
It will look nice via export -> save as PDF and windows() -> save as... too.
An example (2400%):

Related

rayshader 3D ggplots - issue with z values

I am trying to exploit some features of R to plot some crypto data. I am trying to use some examples found at https://www.tylermw.com/3d-ggplots-with-rayshader/
but I am having an issue since on the Z axis I do not get any data. I have on the x,-axis time and price and I want to plot the volume on the z-axis (third column of the file). At the moment I do not see the z values of the volume.
I am sending the R script that I am using:
library(tidyverse)
library(viridis)
library(rayshader)
library(ggplot2)
dec = "."
btcUSDT <- read.csv("test orderbook/data/BTC_USDT 20220720_r.txt",header=TRUE,sep=";",dec=dec,strip.white = TRUE)
head(btcUSDT)
class(btcUSDT$time)
class(btcUSDT$price)
class(btcUSDT$volume)
btcUSDT %>%
ggplot(aes(x = time, y = price) ) +
geom_tile(aes(fill = volume),size=1,color="black") +
scale_x_continuous("Time") +
scale_y_discrete("Price") +
ggtitle("USDT order book") +
labs(caption = "2022-07-23 data") +
theme(axis.text = element_text(size = 12),
title = element_text(size = 12,face="bold"),
panel.border= element_rect(size=2,color="black",fill=NA)) ->
nn_gg
plot_gg(nn_gg, multicore = TRUE, width = 6, height = 5.5, scale = 300,
background = "#afceff",shadowcolor = "#3a4f70")
And I am sending a few rows of my sample data:
head(btcUSDT)
time price volume
1 1.658332e+12 24177.8 1.533
2 1.658332e+12 24178.3 1.535
3 1.658332e+12 24179.1 3.650
4 1.658332e+12 24179.8 3.950
5 1.658332e+12 24179.9 4.241
6 1.658332e+12 24180.0 35.546
class(btcUSDT$time)
[1] "numeric"
class(btcUSDT$price)
[1] "numeric"
class(btcUSDT$volume)
[1] "numeric"
And an image result that I get
Please note that samples from https://www.tylermw.com/3d-ggplots-with-rayshader/ are reproduced properly in my R Studio so all libraries works fine.
The file with data that I am using is available here Data used
Can anyone help to solve the problem?
Thanks
I have changed the data set and values of z axis are plotted but it seems that these have not the correct size (z values seems small). In the previous data set z ranges are [0.60] now are [0,300] and this is the new result that i get
new 3d snapshot
The R script is pretty much the same:
library(tidyverse)
library(viridis)
library(rayshader)
library(ggplot2)
dec = "."
binancebtcUSDT <- read.csv("test orderbook/data/btcusdtbinance 20220720.csv",header=TRUE,sep=",",dec=dec,strip.white = TRUE)
head(binancebtcUSDT)
class(binancebtcUSDT$time)
class(binancebtcUSDT$price)
class(binancebtcUSDT$volume)
max(binancebtcUSDT$price)
min(binancebtcUSDT$price)
max(binancebtcUSDT$volume)
min(binancebtcUSDT$volume)
binancebtcUSDT %>%
ggplot(aes(x = time, y = price)) +
geom_tile(aes(color = volume),size=3, alpha= 0.1) +
scale_color_gradient(low = "dark red", high = "steelblue", na.value = NA) +
scale_x_continuous("Time", expand=c(0,0)) +
scale_y_discrete("Price", expand=c(0,0)) +
ggtitle("Binance BTC/USDT order book") +
labs(caption = "2022-07-20 data") +
coord_cartesian(ylim=c(23418.3, 24196.3), xlim=c(1658331502525,1658339456644)) +
theme(axis.text = element_text(size = 12),
title = element_text(size = 12,face="bold"),
panel.border= element_rect(size=2,color="black",fill=NA)) ->
binance_plt
plot_gg(binance_plt, multicore = TRUE, width = 6, height = 5.5, scale = 300,
background = "#afceff",shadowcolor = "#3a4f70")
I have tried to change the scale in plot_gg but only the z scale outside the plot changes. This is the new dataset that I am using new data set
Any idea to solve the new issue? Thanks
I have found out that the data set contains a few elements in the range 100-300 and this causes such representation issue. Is there a way to change the scale of the z values?
looks like "fill" is not the right argument for geom_tile: you need to use color:
btcUSDT %>%
ggplot(aes(x = time, y = price) ) +
#geom_point(aes(color=volume))+
geom_tile(aes(color = volume),size=3, alpha= 0.1)+
scale_color_gradient(low = "dark red", high = "steelblue", na.value = NA)

When using a color transformation in ggplot2, change the legend gradient instead of the legend break positions

Suppose I have a raster plot where the fill color gradient isn't used very efficiently because the values are skewed, like this:
library(ggplot2)
set.seed(20)
d = expand.grid(x = seq(0, 10, len = 100), y = seq(0, 10, len = 100))
d = transform(d, z =
1e-4 * ((x - 2)^2 + (2*y - 4)^2 + 10*rnorm(nrow(d)))^2)
ggplot(d) +
geom_raster(aes(x, y, fill = z)) +
scale_fill_distiller(palette = "Spectral",
limits = c(0, 12), breaks = 0 : 12) +
theme(legend.key.height = unit(20, "mm"))
I can quantile-transform the color scale like this:
ggplot(d) +
geom_raster(aes(x, y, fill = z)) +
scale_fill_distiller(palette = "Spectral",
limits = c(0, 12), breaks = 0 : 12,
trans = scales::trans_new("q",
function(x) ecdf(d$z)(x),
function(x) unname(quantile(d$z, x)))) +
theme(legend.key.height = unit(20, "mm"))
I like what this does for the main part of the plot, but not the legend. The legend uses the same gradient as the original, while moving the breaks according to the transformation. I'd prefer to keep the breaks where they are, while transforming the gradient instead. Also, I'd like to avoid the floating-point noise that's been added to the break labels. How can I accomplish these changes?
I had a very similar idea to chemdork123, but wanted to stay a bit closer to the quantile idea. The idea is to set an exact palette of colours (i.e., one colour for every value) and space this out such that it follows the data.
library(ggplot2)
library(scales)
#> Warning: package 'scales' was built under R version 4.0.3
set.seed(20)
d = expand.grid(x = seq(0, 10, len = 100), y = seq(0, 10, len = 100))
d = transform(d, z =
1e-4 * ((x - 2)^2 + (2*y - 4)^2 + 10*rnorm(nrow(d)))^2)
# The 'distiller' palette outside of the scale,
# we need this to generate `length(d$z)` number of colours.
pal <- gradient_n_pal(brewer_pal(palette = "Spectral", direction = -1)(7))
ggplot(d) +
geom_raster(aes(x, y, fill = z)) +
scale_fill_gradientn(
colours = pal(c(0, rescale(seq_along(d$z)), 1)), # <- extra 0, 1 for out-of-bounds
limits = c(0, 12), breaks = 0:12,
values = c(0, rescale(sort(d$z), from = c(0, 12)), 1) # <- extra 0, 1 again
) +
theme(legend.key.height = unit(10, "mm"))
Created on 2021-03-31 by the reprex package (v1.0.0)
You can use the values argument for the scale_fill_distiller() function. The distiller scales extend brewer to continuous scales by interpolating 7 colors from any palette. By default, the scaling is linearly applied from 0 (lowest value on the scale) to 1 (highest value on the scale). You can recreate this mapping via: scales::rescale(1:7). If you supply a new vector to the values argument, you can remap each of the 7 colors to a new location. You do not have to supply 7 values - the rest are interpolated linearly - just as long as you specify the max at 1 (or you'll cut the scale).
Best way is to play around with it - I've tried mapping to specific functions before, but honestly it tends to work for me the best when I just mess with the numbers until I get something I like:
ggplot(d) +
geom_raster(aes(x, y, fill = z)) +
scale_fill_distiller(palette = "Spectral", values = c(0,0.05,0.1, 0.5,1)) +
theme(legend.key.height = unit(20, "mm"))

Issues with cross-correlation function (ccf) to ggplot

I am using the cross-correlation function (ccf) to show day lags in discharge from different springs. I used ccf to ggplot code for better visualization. My results looked like the image below and the code worked flawlessly, but then I went to re-run the code and now I keep getting an error. I had originally modified the source code slightly, but once I had the error, I went back to the original source code and the error persists!
Data, code and problem:
# example data
big = runif(60)
mangum = runif(61:120)
hydro = data.frame(big, mangum)
# Using the ccf to ggplot function (from the above link)
xcf_plot <- function(df, x, y, title = "Cross Correlation"){
df_x <- eval(substitute(x), df)
df_y <- eval(substitute(y), df)
ccf.object <- ccf(df_x, df_y, plot = FALSE)
output_table <- cbind(lag = ccf.object$lag,
x.corr = ccf.object$acf) %>%
as_tibble() %>%
mutate(cat = ifelse(x.corr > 0, "green", "red"))
output_table %>%
ggplot(aes(x = lag, y = x.corr)) +
geom_bar(stat = "identity", aes(fill = cat))+
scale_fill_manual(values = c("#339933", "#cc0000"))+
ylab("Cross correlation")+
scale_y_continuous(limits = c(-1, 1))+
theme_bw()+
theme(legend.position = "none",
plot.title = element_text(size=10))+
ggtitle(title) -> p
ggsave(paste(title, ".jpg"), plot = p, height = 2.7, width = 4, units = "in")
}
# The only thing I originally changed from the source code was ".svg" to ".jpg",
# "theme_economist()" to "theme_bw()" and colors.
# run the function
xcf_plot(df = hydro, x = hydro$big, y = hydro$mangum, title = "big and mangum")
Error Message:
Error in ifelse(x.corr > 0, "green", "red") : object 'x.corr' not
found
Any idea why this occurring? This is especially weird because I was able to use this exact same code previously and it worked flawlessly:
.
Here's my session info:
R version 3.4.3 (2017-11-30),
Platform: x86_64-w64-mingw32/x64 (64-bit),
Running under: Windows 10 x64 (build 16299)

How can I add annotation in ggplotly animation?

I am creating animated plotly graph for my assignment in r, where I am comparing several models with various number of observations. I would like to add annotation showing what is the RMSE of the current model - this means I would like to have text that changes together with slider. Is there any easy way how to do that?
Here is my dataset stored on GitHub. There already is created variable with RMSE: data
The base ggplot graphic is as follows:
library(tidyverse)
library(plotly)
p <- ggplot(values_predictions, aes(x = x)) +
geom_line(aes(y = preds_BLR, frame = n, colour = "BLR")) +
geom_line(aes(y = preds_RLS, frame = n, colour = "RLS")) +
geom_point(aes(x = x, y = target, frame = n, colour = "target"), alpha = 0.3) +
geom_line(aes(x = x, y = sin(2 * pi * x), colour = "sin(2*pi*x)"), alpha = 0.3) +
ggtitle("Comparison of performance) +
labs(y = "predictions and targets", colour = "colours")
This is converted to plotly, and I have added an animation to the Plotly graph:
plot <- ggplotly(p) %>%
animation_opts(easing = "linear",redraw = FALSE)
plot
Thanks!
You can add annotations to a ggplot graph using the annotate function: http://ggplot2.tidyverse.org/reference/annotate.html
df <- data.frame(x = rnorm(100, mean = 10), y = rnorm(100, mean = 10))
# Build model
fit <- lm(x ~ y, data = df)
# function finds RMSE
RMSE <- function(error) { sqrt(mean(error^2)) }
library(ggplot2)
ggplot(df, aes(x, y)) +
geom_point() +
annotate("text", x = Inf, y = Inf, hjust = 1.1, vjust = 2,
label = paste("RMSE", RMSE(fit$residuals)) )
There seems to be a bit of a problem converting between ggplot and plotly. However this workaround here shows a workaround which can be used:
ggplotly(plot) %>%
layout(annotations = list(x = 12, y = 13, text = paste("RMSE",
RMSE(fit$residuals)), showarrow = F))
Here's an example of adding data dependent text using the built in iris dataset with correlation as text to ggplotly.
library(plotly)
library(ggplot2)
library(dplyr)
mydata = iris %>% rename(variable1=Sepal.Length, variable2= Sepal.Width)
shift_right = 0.1 # number from 0-1 where higher = more right
shift_down = 0.02 # number from 0-1 where higher = more down
p = ggplot(mydata, aes(variable1,variable2))+
annotate(geom = "text",
label = paste0("Cor = ",as.character(round(cor.test(mydata$variable1,mydata$variable2)$estimate,2))),
x = min(mydata$variable1)+abs(shift_right*(min(mydata$variable1)-max(mydata$variable1))),
y = max(mydata$variable2)-abs(shift_down*(min(mydata$variable2)-max(mydata$variable2))), size=4)+
geom_point()
ggplotly(p) %>% style(hoverinfo = "none", traces = 1) # remove hover on text

ggplot2 vs cowplot, Error in FUN("text"[[1L]], ...) :

I'm trying to use cowplot to combine some ggplot2 plots. It should be straightforward, but something in my R or Rstudio surly is broken. What I don't know. I can get it to work with grid.arrange, but the output in my rmarkdown file does not come out as nicely. I broke down my code to the minimum amount to recreate the error, and out of rmarkdown
library(ggplot2)
library(Hmisc)
library(cowplot)
x <- c(1, 8, 9)
y <- c(1, 5, 9)
supply1 <- data.frame(bezier(x, y, evaluation = 500))
g1 <- ggplot(x = 0:10, y = 0:10, geom = "blank") +
geom_path(data = supply1, aes(x = x, y = y), size = 1, colour = "BLUE")
g2 <- ggplot(x = 0:10, y = 0:10, geom = "blank") +
geom_path(data = supply1, aes(x = x+1.5, y = y+1.5), size = 1, colour = "RED")
plot_grid(g1, g2,
ncol = 2,
nrow = 1)
I get this error:
Error in FUN("text"[[1L]], ...) :
Theme element 'text' has NULL property: margin, debug
I have to detach cowplot, but can get something close with gridExtra using this code:
library(ggplot2)
library(Hmisc)
library(gridExtra)
x <- c(1, 8, 9)
y <- c(1, 5, 9)
supply1 <- data.frame(bezier(x, y, evaluation = 500))
g1 <- ggplot(x = 0:10, y = 0:10, geom = "blank") +
geom_path(data = supply1, aes(x = x, y = y), size = 1, colour = "BLUE")
g2 <- ggplot(x = 0:10, y = 0:10, geom = "blank") +
geom_path(data = supply1, aes(x = x+1.5, y = y+1.5), size = 1, colour = "RED")
grid.arrange(g1,g2,
ncol = 2,
nrow = 1)
This code outputs:
grid.arrange plot
Turns out I get the "Error in FUN message" if I try to make any ggplot with both the ggplot2 and cowplot libraries loaded. R 3.1.3, RStudio 0.99.903, cowplot 0.4.0, ggplot2 2.1.0
I have reinstalled everything at least twice, and get the same error situation on a different computer. I can get it to work in a limited fashion. If I wait to call the cowplot library after all other code is run except the plot_grid() chunk, then it will knit and give me the cowplot output. I can not recreate this in a R script only in Rmarkdown, but then I have to have it be the final chunk of the markdown, any ggplot attempts after it will cause the knit to fail.
Short term I used grid.arrange() and just lived with the results, long term I would like to have cowplot as an option.
Any ideas or suggestions?
Apparently it's a bug that has been fixed since R 3.3.1 so upgrade to this version or newer and it should go away.

Resources