How to change markers on time series with plotly? - r

I have a dataframe containing time series data, formed by 3 columns. time, variable and category. I want to plot the time in the x axis and the variable in the y axis, and I want to make groups based on category. Additionally, I would like to modify the default markers created by plotly, so they display a rounded value of the variable.
Consider the following example:
var = rnorm(150)
var[51:100] = var[51:100] +5
var[101:150] = var[101:150] +10
time = seq(as.Date('2018-01-01'), as.Date('2018-01-01')+49, by = 'days')
df = tibble(var = var,
time = rep(time, 3),
category = c(rep('a', 50), rep('b', 50), rep('c', 50)))
head(df)
var time category
<dbl> <date> <chr>
1 0.330 2018-01-01 a
2 -0.786 2018-01-02 a
3 -0.838 2018-01-03 a
4 -0.0719 2018-01-04 a
5 0.0320 2018-01-05 a
6 -1.16 2018-01-06 a
library(plotly)
df %>% group_by(category) %>%
plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers')
This generates the kind of plot that I want: see here, but when I try to modify the the markers:
df %>% group_by(category) %>%
plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers') %>%
add_markers(text = ~ paste("<b>Variable:</b> ", round(var, 2),
"<br />",
"<b>Time:</b> ", time), hoverinfo = "text")
It transforms the plot drawing just the dots but not the lines.see here. If I try to force adding the lines with the command add_lines() then I have a double legend, with values for the dots and the lines separatedly.
df %>% group_by(category) %>%
plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers') %>%
add_markers(text = ~ paste("<b>Variable:</b> ", round(var, 2),
"<br />",
"<b>Time:</b> ", time), hoverinfo = "text") %>%
add_lines()
Is there a way to plot a time series with plotly that includes lines, and customized markers? Im sorry if this is a silly question, I am quite new to plotly.

If you want one trace with both markers and lines then stick with the plot_ly function instead of adding traces. Try this:
library(plotly)
df %>%
group_by(category) %>%
plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers', type = "scatter",
text = ~ paste("<b>Variable:</b> ", round(var, 2),
"<br />",
"<b>Time:</b> ", time), hoverinfo = "text")

Related

Plotly wrongly filling gaps based on color factor in R

I am simply trying to get every month of data to plot the same color.
Plotly is falsely plotting lines that connect each factor color together, generating a giant mess on the chart.
connectgaps = FALSE does not work, because the gaps are not in the data. They are being generated by plotly on the ~factor(month), which colors each month the same.
This has something to do with multiple observations of the factor, rather than just one. If the factor was based on year, rather than month, no line traces would occur.
How can I remove these lines? Thank you!
library(tidyverse)
library(lubridate)
library(plotly)
start_date <- as.Date('2020-1-1')
end_date <- as.Date('2023-2-5')
d1 <- tibble::tibble(date = seq(min(start_date), max(end_date), by = "1 day"))
d2 <- tibble::tibble(rnorm(1132,2))
d3 <- data.frame(d1,d2)
d3 <- d3 %>% mutate(month = month(date))
colnames(d3) <- c('date', 'var', 'month')
plot_ly(d3, x = ~date, y = ~var, type = "scatter", mode = "lines", color = ~factor(month), connectgaps =FALSE)
You could add another column which is the year so you can group on each year using group_by to prevent connecting the lines per month for each year like this:
start_date <- as.Date('2020-1-1')
end_date <- as.Date('2023-2-5')
library(lubridate)
library(dplyr)
library(plotly)
d1 <- tibble::tibble(date = seq(min(start_date), max(end_date), by = "1 day"))
d2 <- tibble::tibble(rnorm(1132,2))
d3 <- data.frame(d1,d2)
d3 <- d3 %>% mutate(month = month(date),
year = year(date))
colnames(d3) <- c('date', 'var', 'month', 'year')
d3 %>%
group_by(year) %>%
plot_ly(x = ~date, y = ~var, type = "scatter", mode = "lines", color = ~factor(month))
Created on 2023-02-05 with reprex v2.0.2
Idea nr. 2:
library(dplyr)
library(lubridate)
library(plotly)
d3 %>%
mutate(year = year(date)) %>%
group_by(year) %>%
plot_ly(x = ~ yday(date)) %>%
add_lines(y = ~var,
color = ~ factor(month))
To answer you question with the lines:
In ggplot when we use group = 1 like:
ggplot(d3, aes(x = date, y = var, group = 1, color = factor(month)))+
geom_line()
We get:

Combine "grouped" and "stacked" bars

I am trying to combine a stacked bar and a simple grouped bar on one X axis in R-plotly. Here is a reproducible sample of code I am using:
library(data.table)
library(magrittr)
library(plotly)
DT <- data.frame("year" = c(2019, 2020, 2021),
"example_var1" = c(12872100, 69436460, 8129560),
"example_var2" = c(25589160, 19671712, 19648085),
"example_var3" = c(15889160, 27671712, 19648085))
setDT(DT)
DT <- melt(DT, id.vars = "year")
DT[, ratio := paste0(round(value / sum(value) * 100, digits = 0), "%"), by = year]
# I would like to select 'example_var1' and 'example_var2 ' only for this part
my_plot <-
plot_ly(
DT,
x = ~ year,
y = ~ value, # select 'example_var1' and 'example_var2'
type = "bar",
name = ~ variable,
text = ~ ratio,
textposition = 'auto'
) %>%
layout (barmode = "stack")
# I would like to select 'example_var3' only for this part
my_plot <- my_plot %>%
add_trace(
x = ~ year,
y = ~ value, # select 'example_var2'
type = "bar",
name = ~ variable,
text = ~ ratio,
textposition = 'auto'
) %>%
layout (barmode = "group")
I don't know how to plot a serie of a stacked bar and a group bar in one plot using the same X axis.
I can't find a way to determine that variables "example_var1" and "example_var2" should plotted together on a stacked bar and variable "example_var3" should be plotted separately as a group bar.
Below a plot that I would like to get:
I am not aware of a straightforward solution for this (read more here:
Combination of grouped and stacked bar chart ). But we can find a workaround by editing the data and modifying the axis. See below;
DT1 <- DT[variable =="example_var3", year := year + 0.4][]
my_plot <-
plot_ly(
DT1,
x = ~ year,
y = ~ value,
type = "bar",
name = ~ variable,
text = ~ ratio,
textposition = 'auto'
) %>%
layout (barmode = "stack",
xaxis = list(
ticktext = list(2019, 2020, 2021),
tickvals = lapply(list(2019, 2020, 2021), `+`, 0.2),
tickmode = "array"
))

R: Updating Hover Text

I am using the R programming language. I made the following interactive graph using the plotly library:
library(dplyr)
library(ggplot2)
library(shiny)
library(plotly)
library(htmltools)
library(dplyr)
#generate data
set.seed(123)
######
var = rnorm(731, 85,25)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
data = data.frame(var,date)
vals <- 90:100
combine <- vector('list', length(vals))
count <- 0
for (i in vals) {
data$var_i = i
data$new_var_i = ifelse(data$var >i,1,0)
#percent of observations greater than i (each month)
aggregate_i = data %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(new_var_i))
#combine files together
aggregate_i$var = i
aggregate_i$var = as.factor(aggregate_i$var)
count <- count + 1
combine[[count]] <- aggregate_i
}
result_2 <- bind_rows(combine)
result_2$group = "group_b"
result_2$group = as.factor(result_2$group)
graph <-ggplot(result_2, aes(frame = var, color = group)) + geom_line(aes(x=month, y=mean, group=1))+ theme(axis.text.x = element_text(angle=90)) + ggtitle("title") + facet_wrap(. ~ group)
graph = ggplotly(graph)
When the user moves the mouse over any point on the graph, the following information is displayed (hover text):
I am trying to add more information to the hover text. For example:
result_2$tot = mean(result_2$mean)
> head(result_2)
# A tibble: 6 x 5
month mean var group tot
<chr> <dbl> <fct> <fct> <dbl>
1 2014-01 0.387 90 group_b 0.364
2 2014-02 0.429 90 group_b 0.364
3 2014-03 0.452 90 group_b 0.364
4 2014-04 0.367 90 group_b 0.364
5 2014-05 0.355 90 group_b 0.364
6 2014-06 0.433 90 group_b 0.364
Yet, when I make a new graph using this result_2 file, the new information does not appear in the hover text:
graph <-ggplot(result_2, aes(frame = var, color = group)) + geom_line(aes(x=month, y=mean, group=1))+ theme(axis.text.x = element_text(angle=90)) + ggtitle("title") + facet_wrap(. ~ group)
graph = ggplotly(graph)
#view graph
graph
Can someone please shoe me how to fix this problem?
Thanks
If you want full control of your hoverinfo its actually best to create a plotly chart rather than a ggplot and then use ggplotly(). If you have only one group in result_2 as in your example above you can use
result_2 %>%
plot_ly(x=~month, y=~mean, color=~group) %>%
group_by(group) %>%
add_lines(frame=~var,hoverinfo = "text",
text = ~ paste0("Month: ",month, "<br>",
"Mean: ", mean, "<br>",
"Total: ", mean(mean))) %>%
layout(title = list(text = "title"),
xaxis = list(tickangle = -90, tickformat = "%m-%Y"))
or if you have > 1 group in result_2 and you want to facet by group as indicated in your ggplot you can do:
result_2 %>%
group_by(group) %>%
do(
plot = plot_ly(data =., x=~month, y=~mean, color=~group) %>%
add_lines(frame=~var,hoverinfo = "text",
text = ~ paste0("Month: ",month, "<br>",
"Mean: ", mean, "<br>",
"Total: ", mean(mean))) %>%
layout(title = list(text = "title"),
xaxis = list(tickangle = -90, tickformat = "%m-%Y"))
) %>%
subplot(shareX = TRUE, shareY = FALSE, nrows = 2)
But this won't work if you have only one group hence the two options provided.
You can create any function and write anything you want in the text = ~paste0() part and it will show up in your hoverinfo.

Spaghetti plot using ggplot in R?

I would like to produce a speghatii plot where i need to see days of the year on the x-axis and data on the y-axis for each Year. I would then want a separate year that had data for only 3 months (PCPNewData) to be plotted on the same figure but different color and bold line. Here is my sample code which produce a graph (attached) where the data for each Year for a particular Day is stacked- i don't want bar graph. I would like to have a line graph. Thanks
library(tidyverse)
library(tidyr)
myDates=as.data.frame(seq(as.Date("2000-01-01"), to=as.Date("2010-12-31"),by="days"))
colnames(myDates) = "Date"
Dates = myDates %>% separate(Date, sep = "-", into = c("Year", "Month", "Day"))
LatestDate=as.data.frame(seq(as.Date("2011-01-01"), to=as.Date("2011-03-31"),by="days"))
colnames(LatestDate) = "Date"
NewDate = LatestDate %>% separate(Date, sep = "-", into = c("Year", "Month", "Day"))
PCPDataHis = data.frame(total_precip = runif(4018, 0,70), Dates)
PCPNewData = data.frame(total_precip = runif(90, 0,70), NewDate)
PCPDataHisPlot =PCPDataHis %>% group_by(Year) %>% gather(key = "Variable", value = "Value", -Year, -Day,-Month)
ggplot(PCPDataHisPlot, aes(Day, Value, colour = Year))+
geom_line()+
geom_line(data = PCPNewData, aes(Day, total_precip))
I would like to have a Figure like below where each line represent data for a particular year
UPDATE:
I draw my desired figure with hand (see attached). I would like to have all the days of the Years on x-axis with its data on the y-axis
You have few errors in your code.
First, your days are in character format. You need to pass them in a numerical format to get line being continuous.
Then, you have multiple data for each days (because you have 12 months per year), so you need to summarise a little bit these data:
Pel2 <- Pelly2Data %>% group_by(year,day) %>% summarise(Value = mean(Value, na.rm = TRUE))
Pel3 <- Pelly2_2011_3months %>% group_by(year, day) %>% summarise(total_precip = mean(total_precip, na.rm = TRUE))
ggplot(Pel2, aes(as.numeric(day), Value, color = year))+
geom_line()+
geom_line(data = Pelly2_2011_3months, aes(as.numeric(day), y= total_precip),size = 2)
It looks better but it is hard to apply a specific color pattern
To my opinion, it will be less confused if you can compare mean of each dataset, such as:
library(tidyverse)
Pel2 <- Pelly2Data %>% group_by(day) %>%
summarise(Mean = mean(Value, na.rm = TRUE),
SEM = sd(Value,na.rm = TRUE)/sqrt(n())) %>%
mutate(Name = "Pel_ALL")
Pel3 <- Pelly2_2011_3months %>% group_by(day) %>%
summarise(Mean = mean(total_precip, na.rm = TRUE),
SEM = sd(total_precip, na.rm = TRUE)/sqrt(n())) %>%
mutate(Name = "Pel3")
Pel <- bind_rows(Pel2,Pel3)
ggplot(Pel, aes(x = as.numeric(day), y = Mean, color = Name))+
geom_ribbon(aes(ymin = Mean-SEM, ymax = Mean+SEM), alpha = 0.2)+
geom_line(size = 2)
EDIT: New graph based on update
To get the graph you post as a drawing, you need to have the day of the year and not the day of the month. We can get this information by setting a date sequence and extract the day of the year by using yday function from `lubridate package.
library(tidyverse)
library(lubridate)
Pelly2$Date = seq(ymd("1990-01-01"),ymd("2010-12-31"), by = "day")
Pelly2$Year_day <- yday(Pelly2$Date)
Pelly2_2011_3months$Date <- seq(ymd("2011-01-01"), ymd("2011-03-31"), by = "day")
Pelly2_2011_3months$Year_day <- yday(Pelly2_2011_3months$Date)
Pelly2$Dataset = "ALL"
Pelly2_2011_3months$Dataset = "2011_Dataset"
Pel <- bind_rows(Pelly2, Pelly2_2011_3months)
Then, you can combine both dataset and represent them with different colors, size, transparency (alpha) as show here:
ggplot(Pel, aes(x = Year_day, y = total_precip, color = year, size = Dataset, alpha = Dataset))+
geom_line()+
scale_size_manual(values = c(2,0.5))+
scale_alpha_manual(values = c(1,0.5))
Does it answer your question ?

Make a boxplot in highchart with a date object in the x axis

I am trying to make a boxplot in highchart to include it in a shiny app, along with another graph I already have.
The problem is that boxplot, as far as I can tell, do not behave like other plots and when you map a date to the x-axis, it is treated as a character string, this mean: the plot display the entire date ex: "2018-04-01" an not Apr'18 like it does in other plots.
Here I put a little reprex of what I have done
# Packages
library(tidyverse)
library(lubridate)
library(highcharter)
library(magrittr)
library(plotly)
# Data
stocks <- data.frame(
time = rep(as.Date('2009-01-01') + month(1:12), times = 10),
stock_price = rnorm(120, 0, 1)
)
# line plot
stocks %>%
group_by(time) %>%
summarise(mean_price = mean(stock_price)) %>%
hchart(.,
type = "line",
hcaes(x = "time",
y = "mean_price"))
# Box plot first try
# hchart boxplot
stocks %$%
hcboxplot(x = stock_price, time) %>%
hc_chart(type = "column")
After doing this first try, I try to create an abbreviated date and map it to the x-axis as follows, but the boxes are shown ordered alphabetically not chronologically
# hchart boxplot
stocks %>%
mutate(month = month(time, label = T),
year = str_extract(as.character(year(time)), "..$"),
time2 = paste(month, year, sep = "'")) %$%
hcboxplot(x = stock_price, time2) %>%
hc_chart(type = "column")
My desired output is a plot with x-axis like the line plot or like plotly's output
stocks %>%
group_by(time) %>%
plot_ly(x = ~time, y = ~stock_price, type = "box")
With the help of arrange() and fct_inorder(), I believe I've achieved your desired outcome:
stocks %>%
arrange(time) %>%
mutate(
month = month(time, label = T),
year = str_extract(as.character(year(time)), "..$"),
time2 = fct_inorder(paste(month, year, sep = "'"))
) %$%
hcboxplot(x = stock_price, time2) %>%
hc_chart(type = "column")

Resources