how to create a bar chart with a dual axis? - r

Consider this simple example
library(lubridate)
library(lattice)
library(latticeExtra)
library(tibble)
library(dplyr)
mydf <- tibble(time = c(ymd('2019-01-01'),
ymd('2019-01-02'),
ymd('2019-01-03'),
ymd('2019-01-04'),
ymd('2019-01-05')),
var1 = c(2,2,2,2,1),
var2 = c(2,1,1,4,5),
var3 = c(200, 200, 400, 500, 230))
Now this works
p1 <- mydf %>%
barchart(var1 + var2 ~ time,
data = .,
stack = TRUE,
horiz = FALSE,
par.settings = simpleTheme(col = c('red', 'blue'),
fill = c('red', 'blue'),
alpha = c(0.2)),
auto.key = TRUE)
and this works as well
p2 <- mydf %>%
xyplot(var3 ~ time, data = ., type = 'l')
However, combining them with latticeExtra::doubleYscale() does not work. The line is invisible (see below)
latticeExtra::doubleYScale(p1, p2, use.style = FALSE)
Strangely enough, the dual y scale is there, but the line is missing. Any ideas?
Thanks!!

I simplified your data a bit.
Using as.layer (also from latticeExtra) rather than doubleYScale:
library(lattice)
library(latticeExtra)
mydf <- data.frame(t=1:5,x=c(2,2,2,2,1),
y=c(2,1,1,4,5),z=c(200,200,400,500,230))
p1 <- barchart(x+y~t,mydf,stack=TRUE,horiz=FALSE,
par.settings = simpleTheme(col = c('red', 'blue'),
fill = c('red', 'blue'),
alpha = c(0.2)),
auto.key = TRUE)
p2 <- xyplot(z~t,mydf,type="l")
p1+as.layer(p2,x.same=TRUE,y.same=FALSE,outside=TRUE)
I trust it also works with lubridated objects and tibbles.
EDIT: to clarify as.layer is also in latticeExtra package and add the plot.

Using ggplot2, you could do:
library(tidyr)
library(ggplot2)
df1 <- mydf %>%
select(-var3) %>%
pivot_longer(
cols = c(var1, var2),
names_to = "type",
values_to = "value"
)
df2 <- mydf %>%
select(time, var3)
ggplot(df1) +
geom_col(aes(x = time, y = value, fill = type)) +
geom_line(data = df2, aes(x = time, y = var3/100), size = 2) +
ylab("var1, var2") +
scale_y_continuous(sec.axis = sec_axis(~.*100, name = "var3"))

Related

selectize widget of ggplotly highlight not always visible (depends on order of geoms?)

I want to do an interactive scatterplot where I can
highlight individual points
a tooltip shows me the id
search for specific id with a selectize widget
I tried for some time with plotly and ended up with this code
library(tidyverse)
library(plotly)
set.seed(1)
dat <- tibble(id = LETTERS[1:10],
trt = factor(rep(0:1, 5)),
x = rnorm(10),
y = x + rnorm(10, sd = 0.2)) %>%
highlight_key(~id)
dat %>%
{ggplot(., aes(x = x, y = y, group = id, color = trt)) +
geom_point() +
geom_hline(yintercept = 0, linetype = "dashed")} %>%
ggplotly(tooltip = c("id")) %>%
highlight(on = "plotly_hover", selectize = TRUE)
It took my very long to understand that the order of geoms seems to be important
## no color, geom order reversed
## selectize.js widget is completely missing
dat %>%
{ggplot(., aes(x = x, y = y, group = id)) +
geom_hline(yintercept = 0, linetype = "dashed") +
geom_point()} %>%
ggplotly(tooltip = c("id")) %>%
highlight(on = "plotly_hover", selectize = TRUE)
## color by trt, geom order reversed
## selectize.js widget only works for data where t = 0
dat %>%
{ggplot(., aes(x = x, y = y, group = id, color = trt)) +
geom_hline(yintercept = 0, linetype = "dashed") +
geom_point()} %>%
ggplotly(tooltip = c("id")) %>%
highlight(on = "plotly_hover", selectize = TRUE)
Can somebody explain this strange behavior? What if I would like to reverse the order of geoms i.e. hline ploted behind points?

How to superimpose two ggplots

I have 2 ggplots generated by below codes
library(dplyr)
library(ggplot2)
library(ggdist)
set.seed(1)
DF1 = rbind(data.frame('Label' = 'A', val = rnorm(200, 5)), data.frame('Label' = 'B', val = rnorm(500, 10)))
DF2 = rbind(data.frame('Label' = 'A', val = rt(200, 2)), data.frame('Label' = 'B', val = rt(700, 3)))
Plot1 = ggplot(DF1, aes(x = Label, y = val, fill = 'red')) + stat_dotsinterval(position = 'dodge')
Plot2 = ggplot(DF2, aes(x = Label, y = val, fill = 'green')) + stat_dotsinterval(position = 'dodge')
Plot1
Plot2
Those are individual plots, however I want to combine them into just one ggplot with appropriate legend.
Is there any way to do this for above case?
Any pointer will be highly appreciated.
Similar to eipi10's comment:
library(dplyr); library(ggplot2)
bind_rows(DF1, DF2, .id = "src") %>%
mutate(name = if_else(src == "1", "red", "green")) %>%
ggplot(aes(x=Label, y=val, colour=name, fill=name)) +
stat_dotsinterval() +
scale_color_identity(aesthetics = c("fill", "color"), guide = "legend") +
theme(legend.position = "top")

How to unify a legend with different types of scales in ggplot?

I have a data frame separated by 3 different factors. I want to represent this data frame with a scatter plot, using different types of scale for each factor.
I want to use shapes 21, 22 and 24, which are shapes with an outline and a colored filling. However, the filling scale does not appear correctly in the legend. Also, I want to unify the legend so that the labels look something like this (in the MWE I represented these labels with numbers from 1 to 18 (labels = 1:18)):
A, M, V1
A, M, V2
A, M, V3
...
B, O, V2
B, O, V3
I followed the recommendations of this answer, but the resulting plot was not as expected. Does anyone know how I can solve this issue?
library(ggplot2)
Factor1 <- c('A', 'B')
Factor2 <- c('M', 'N', 'O')
Factor3 <- c('V1', 'V2', 'V3')
DF <- expand.grid(Factor1 = Factor1,
Factor2 = Factor2,
Factor3 = Factor3)
DF$Result <- runif(n =18,
min = 0,
max = 100)
DF <- DF[order(DF[, "Result"]), ]
DF$Order <- 1:18
ggplot(data = DF,
aes(x = Order,
y = Result,
fill = Factor1,
shape = Factor2,
size = Factor3)) +
geom_point() +
scale_fill_manual(name = "Legend",
values = c('blue', 'red'),
labels = 1:18) +
scale_shape_manual(name = "Legend",
values = c(21,22,24),
labels = 1:18) +
scale_size_manual(name = "Legend",
values = c(2,4,6),
labels = 1:18)
Following your link will give proper result, but it needs pretty amount of effort....I made an example for Factor1 and Factor2.
DF %>%
rowwise %>%
mutate(Fac = paste0(c(Factor1, Factor2), collapse = "-") %>% as.factor) %>%
ggplot( aes(x = Order,
y = Result,
fill = Fac,
shape = Fac,
size = Factor3)) +
geom_point() +
scale_fill_manual(name = "Legend",
values = c('blue', 'red', 'blue', 'red', 'blue', 'red'),
labels = c("A-M", "B-M", "A-N", "B-N", "A-O", "B-O")) +
scale_shape_manual(name = "Legend",
values = c(21,21,22,22,24,24),
labels = c("A-M", "B-M", "A-N", "B-N", "A-O", "B-O")) +
scale_size_manual(name = "Legend",
values = c(2,4,6),
labels = 1:18)
To combine with Factor3, you may start with
DF %>%
rowwise %>%
mutate(Fac = paste0(c(Factor1, Factor2, Factor3), collapse = "-") %>% as.factor) %>%
ggplot( aes(x = Order,
y = Result,
fill = Fac,
shape = Fac,
size = Fac))

ggplot using facet_wrap of multiple data.frame with different length in R?

I am trying to achieve the attached hand drawn figure using the code below but its showing white spaces for all the years that i do not have data for. Any help would be appreciated.
library(lubridate)
library(tidyverse)
set.seed(123)
D1 <- data.frame(Date = seq(as.Date("2001-07-14"), to= as.Date("2001-07-21"), by="day"),
A = runif(8, 0,10),
D = runif(8,5,15)) %>%
gather(-Date, key = "Variable", value = "Value")
D2 <- data.frame(Date = seq(as.Date("1998-07-14"), to= as.Date("1998-08-30"), by="day"),
A = runif(48, 0,10),
D = runif(48,5,15)) %>%
gather(-Date, key = "Variable", value = "Value")
D <- bind_rows(D1,D2) %>% mutate(Year = year(Date))
my_linetype <- setNames(c("dashed", "solid"), unique(D$Year))
ggplot(data = D, aes(x = Date, y = Value, color = as.factor(Year), linetype = as.factor(Year)))+
geom_line(size = 1.1)+ facet_wrap(~Variable, scales = "free_y", nrow=2)
Desired Out
You can make a dummy Date variable in your data.frame where the year is equal among different groups. In the example below this added in the mutate() statement under the Unyear variable.
D <- bind_rows(D1,D2) %>% mutate(Year = year(Date),
Unyear = {year(Date) <- 0; Date})
my_linetype <- setNames(c("dashed", "solid"), unique(D$Year))
ggplot(data = D, aes(x = Unyear, y = Value, color = as.factor(Year), linetype = as.factor(Year)))+
geom_line(size = 1.1)+ facet_wrap(~Variable, scales = "free_y", nrow=2)

Plotting x axes with increasing and decreasing x-values in R

I have been trying to plot x axes with increasing and the decreasing data values in R
i.e x-axes have values from [60 to 90 to 60], corresponding to different y-values
how can I do this?
This might not be an exact answer but you can use ggplot() and facet_wrap to achieve something similar:
library(ggplot2)
library(dplyr)
library(gridExtra)
# GGPLOT2
x = c(1:50, 50:1)
y = x + rnorm(1000)
group = rep(c("A", "B"), each = 50)
df <- data.frame(x, y, group)
p1 <- df %>%
filter(group == "A") %>%
ggplot(aes(x, y, color = "A")) + geom_point() + ggtitle("UP") + guides(color = F)
p2 <- df %>%
filter(group == "B") %>%
ggplot(aes(x, y, color = "B")) + geom_point() + scale_x_reverse() + ggtitle("DOWN") + guides(color = F)
grid.arrange(p1, p2, nrow = 1)
Recently the plotly package has been receiving a lot of attention. You could do the following using ploy_ly():
# PLOTLY
library(plotly)
p <- df %>%
filter(group == "A") %>%
plot_ly(x = x, y = y, mode = "markers") %>%
layout(xaxis = list(domain = c(0, 0.5)))
p <- df %>%
filter(group == "A") %>%
add_trace(p, x = x, y = y, mode = "markers", xaxis = "x2", yaxis = "y2", data = .) %>%
layout(xaxis2 = list(autorange = "reversed",
domain = c(0.5, 1)),
yaxis2 = list(overlaying = "y",
side = "right"))
p
Is this what you are looking for?
x = c(1,2,3,4,5,6,7,6,5,4,3,2,1)
y = c(4,5,6,7,8,11,12,23,45,25,11,16,2)
ggplot(data.frame(x=1:length(x), y))+
geom_point(aes(x=x, y=y))+
scale_x_discrete(labels = as.character(x))
This will not work so well if x is not in the proper order or has missing values. You should consider adding a MWE along with your attempts in your question.

Resources