Grouping dataframe causes error when it is combined with plotl_ly() - r

Im trying to display in my hovertext Name,lab and Week by creating a list named customdata which I pass to plot_ly(). The problem is that Im getting the error Size 2: Columns x, y, color, hovertemplate, .plotlyGroupIndex, and 2 more. * Size 6: Column customdata. [34mℹ[39m Only values of size one are recycled. but I do not understand why there is a difference in size. I mean that I get a new dataset after adding lab and cannot make it work due to issue above
library(plotly)
library(dplyr)
full_data<-data.frame("Name"=c("Q1","Q2","Q3","Q1","Q2","Q3"),"Values"=c(245645,866556,26440,65046,641131,463265),
"Week"=c("a","b","c","d","e","f"))
desc <- full_data %>%
group_by(Name,Week) %>%
summarise(values = sum(Values)) %>%
mutate(lab = scales::label_number_si(accuracy = 0.1)(values))
plot_ly(desc,
x = ~Week,
y = ~values,
#text = ~values,
color = ~Name,
colors = c("#60ab3d","#6bbabf","#c4d436","#3e5b84","#028c75","red"),
customdata = mapply(function(x,y) list(x,y), desc$lab, desc$Name, SIMPLIFY = FALSE)) %>%
add_trace(
type = 'scatter',
mode = 'lines+markers',
hovertemplate = paste(
"%{x}",
"%{customdata[0]}",
"%{customdata[1]}",
"<extra></extra>",
sep = "\n"),
hoveron = 'points')

You just need to format your customdata with the vector of character instead
plot_ly(desc,
x = ~Week,
y = ~values,
#text = ~values,
color = ~Name,
# I saw that you have only 3 Name in the sample data so I reduce
# this to only 3 color instead of 7 like you have originally
colors = c("#60ab3d","#6bbabf", "#c4d436"),
# combine the lab & Name from desc data using paste0
customdata = paste0(desc$lab, "\n", desc$Name)) %>%
add_trace(
type = 'scatter',
mode = 'lines+markers',
hovertemplate = paste(
"%{x}",
"%{customdata}",
sep = "\n"),
hoveron = 'points')
Here is the output

Related

R+Plotly: Customize Legend Entries

I must be having trouble with less than a one liner,
but have a look at the snippet below: I cannot the legend option to enter the text that I want in the legend as the name of the species (say, "foo1", "foo2", "foo3").
Notice that I do not want to change the original (iris in this case) dataset.
Any suggestion?
library(tidyverse)
library(plotly)
plot_ly(iris, x = ~Sepal.Length,
y = ~Sepal.Width,
type = 'scatter', color = ~Species,
symbol = ~Species,
mode = 'markers') %>%
layout(legend=list(title=list(text='My title')))
Plotly considers legend names to be associated with each trace rather than with the legend itself. So redefining names has to occur on each trace. If you don't want to modify the original dataset, you'd have to filter it by Species and add the trace with the new name one at a time, with something like this:
library(tidyverse)
library(plotly)
plot_ly(iris %>% filter(Species == "setosa"),
x = ~Sepal.Length,
y = ~Sepal.Width,
type = 'scatter',
color = ~Species,
symbol = ~Species,
mode = 'markers',
name = "foo 1") %>%
add_trace(data = iris %>% filter(Species == "versicolor"),
x = ~Sepal.Length,
y = ~Sepal.Width,
type = 'scatter',
color = ~Species,
symbol = ~Species,
mode = 'markers',
name = "foo 2") %>%
add_trace(data = iris %>% filter(Species == "virginica"),
x = ~Sepal.Length,
y = ~Sepal.Width,
type = 'scatter',
color = ~Species,
symbol = ~Species,
mode = 'markers',
name = "foo 3") %>%
layout(legend=list(title=list(text='My title')))
In a more complex case, it may be best to indeed modify the dataset itself or use a loop. A similar question about a more complex case is here: Manipulating legend text in R plotly and the reference documentation on plotly legend names is here: https://plotly.com/r/legend/#legend-names

R plotly simple boxplot highlighting the most recent value

I probably have a simple question but I can't find a way to achieve what I need. I have a simple boxplot as the following:
end_dt <- as.Date("2021-02-12")
start_dt <- end_dt - (nrow(iris) - 1)
dim(iris)
dates <- seq.Date(start_dt, end_dt, by="1 day")
df <- iris
df$LAST_VAL <- "N"
df[3, 'LAST_VAL'] <- "Y"
df1 <- df[,c("Sepal.Length","LAST_VAL")]
df1$DES <- 'Sepal.Length'
colnames(df1) <- c("VALUES","LAST_VAL","DES")
df2 <- df[,c("Sepal.Width","LAST_VAL")]
df2$DES <- 'Sepal.Width'
colnames(df2) <- c("VALUES","LAST_VAL","DES")
df <- rbind(df1, df2)
fig <- plot_ly(df, y = ~VALUES, color = ~DES, type = "box") %>% layout(showlegend = FALSE)
What I would like to do now is a add a red marker to each box plot just for the value corresponding to LAST_VAL = "Y". This would allow me to see given the distribution of each plot, to see where the most recent value is located.
I tried to use the info on https://plotly.com/r/box-plots/ but I can't figure out how to do this.
Thanks
The following solution ended up to be a bit too long codewise. However, it should give you what you asked for. I think the boxplots should be added afterwards, like:
fig <- plot_ly(df[df$LAST_VAL=="Y",],
x=~DES, y = ~VALUES, color = ~DES, type = "scatter", colors='red') %>%
layout(showlegend = FALSE) %>%
add_boxplot(data = df[df$DES=="Sepal.Length",], x = ~DES, y = ~VALUES,
showlegend = F, color = ~DES,
boxpoints = F, fillcolor = 'white', line = list(color = c('blue'))) %>%
add_boxplot(data = df[df$DES=="Sepal.Width",], x = ~DES, y = ~VALUES,
showlegend = F, color = ~DES,
boxpoints = F, fillcolor = 'white', line = list(color = c('green')))

Removing Unused Subplot in R Plotly

When using plotly (in R), after combining subplots there remains an unused and blank subplot. I've recreated the issue using the ggplot2 dataset mpg below.
library(dplyr)
library(ggplot2)
library(plotly)
audi <- mpg %>%
filter(manufacturer == "audi")
chevy <- mpg %>%
filter(manufacturer == "chevrolet")
fig1 <- plot_ly(audi, x = ~hwy, y = ~year, name = "", type = 'scatter',
mode = "markers", marker = list(color = "blue", symbol = 'x-dot'))
fig2 <- plot_ly(chevy, x = ~hwy, y = ~year, name = "", type = 'scatter',
mode = "markers", marker = list(color = "red", symbol = 'circle'))
fig <- subplot(fig1, fig2)
fig <- fig %>% subplot(shareX = TRUE,shareY = TRUE,which_layout = "merge")
fig <- fig %>% layout(
title = "Audi and Chevy",
xaxis = list(title = "Highway MPG"),
yaxis = list(title = "Year"),
margin = list(l = 100)
)
The only solution I've been able to find is tinkering with the width of the used subplot, but this leaves quite a bit of unused white space on the right and causes the title to be far off to the right (as it adjusts into the center of the used and unused subplots).
Is there a way to remove the unused subplot? If not, is there a way to organize/subset the dataframe such that only one plot needs to be used in the first place?
Thanks!
You can assign the colours based on the manufacturer column:
data.subs <- mpg %>%
filter(manufacturer == "audi" | manufacturer == "chevrolet")
fig <- plot_ly(data.subs, x = ~hwy, y = ~year, name = "",
type = 'scatter', mode = "markers",
marker = list(color = factor(data.subs$manufacturer,
labels = c("red", "blue")),
symbol = 'circle'),
text = factor(data.subs$manufacturer,
labels = c("audi", "chevy")), hoverinfo = 'text'))
fig <- fig %>% layout(
title = "Audi and Chevy",
xaxis = list(title = "Highway MPG"),
yaxis = list(title = "Year"),
margin = list(l = 100)
)
fig
This makes generating multiple subplots unnecessary.

How do I split grouped bar chart in R by variable

I am trying to split the attached grouped bar chart by the variable spec. Two thoughts on best way to do this are by adding facet_grid() or if a filter can be applied to the static output? Can either be done? Any advice appreciated.
a sample is below:
period <- c('201901', '201901', '201904', '201905')
spec <- c('alpha', 'bravo','bravo', 'charlie')
c <- c(5,6,3,8)
e <- c(1,2,4,5)
df <- data.frame(period, spec, c,e)
library(tidyverse)
library(plotly)
plot_ly(df, x =~period, y = ~c, type = 'bar', name = "C 1", marker = list(color = 'lightsteelblue3'))
%>%
add_trace(y = ~e, name = "E 1", marker = list(color = 'Gray')) %>%
layout(xaxis = list(title="", tickangle = -45),
yaxis = list(title=""),
margin= list(b=100),
barmode = 'group'
)
I am not sure if you are plotting what you actually want to achieve? My suggestion is to create your plot using standard ggplot and then use ggplotly.
For this, you also need to reshape your data and make it a bit longer.
library(tidyverse)
library(plotly)
period <- c('201901', '201901', '201904', '201905')
spec <- c('alpha', 'bravo','bravo', 'charlie')
c <- c(5,6,3,8)
e <- c(1,2,4,5)
df <- data.frame(period, spec, c,e) %>%
pivot_longer(cols = c(c,e), names_to = 'var', values_to = 'val')
p <- ggplot(df, aes(period, val, fill = var)) +
geom_col(position = position_dodge()) +
facet_grid(~spec)
ggplotly(p)
It's probably easier to use facets here, but a more "interactive" option would be to use a filter transforms which gives you a drop-down menu in the top left corner of your plot.
spec.val <- unique(df$spec)
plot_ly(
df %>% pivot_longer(-c(period, spec)),
x = ~period, y = ~value, color = ~name,
type = "bar",
transforms = list(
list(
type = "filter",
target = ~spec,
operation = "=",
value = spec.val[1]))) %>%
layout(
updatemenus = list(
list(
type = "drowdown",
active = 0,
buttons = map(spec.val, ~list(
method = "restyle",
args = list("transforms[0].value", .x),
label = .x)))))

How to set different text and hoverinfo text

I am working with the plotly package, and I cannot find a way to display different things on the chart itself and in the hoverinfo.
Here is an example of a barchart:
library(plotly)
library(dplyr)
data(iris)
df <- iris %>%
group_by(Species) %>%
summarise(n = n(),
avg = mean(Sepal.Length))
p1 <- plot_ly(data = df,
x = ~Species,
y = ~n,
type = "bar",
text = ~paste("Species :", Species,
"<br> Avg :", avg),
textposition = "auto",
hoverinfo = "text")
From this code I get this:
And I would like to display the frequency (n) value in each bar instead of the same thing as the hoverinfo.
I have been looking at this thread but the solution described is too complicated for me and I think there must be an easier way to solve this issue.
Something like this?
p1 <- plot_ly(data = df,
x = ~Species,
y = ~n,
type = "bar",
text = ~n,
textposition = "auto",
hoverinfo = "text",
hovertext = paste("Species :", df$Species,
"<br> Avg :", df$avg))

Resources