How do I split grouped bar chart in R by variable - r

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

Related

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

R Plotly Animation Gapminder

I was wondering if is it possible to add annotations to a Plotly Animated Gapminder plot? I mean, I don't need that all the bubbles have annotations, but I would like that some of them had.
Here's an example, the only country that I want to display the name is China.
library(plotly)
library(gapminder)
m <- gapminder[gapminder$country == "China", ]
a <- list(
x = m$gdpPercap,
y = m$lifeExp,
text = m$country,
xref = "x",
yref = "y",
showarrow = TRUE,
arrowhead = 7,
ax = 20,
ay = -40
)
df <- gapminder
fig <- df %>%
plot_ly(
x = ~gdpPercap,
y = ~lifeExp,
size = ~pop,
color = ~continent,
frame = ~year,
text = ~country,
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
) %>% add_markers() %>% layout(annotations = a)
I need that the annotation to follow the China marker. Do you know if this is possible?
Thanks!
Bruno

Plotly stacked bar chart add_trace loop issue

I am building a stacked bar chart in plotly and whenever I run my loop for add_trace, there is an issue as data of the previous trace seems to dissapear while names remain.
p = plot_ly( x = rownames(dist_data), y = as.numeric(dist_data[,1]), type = 'bar', name = colnames(dist_data)[1])%>%
layout(legend = list(x = 0.1, y = 0.9))
for ( j in 2:length(colnames(dist_data)))
{
p = add_trace(p, y = ~as.numeric(dist_data[,j]), type = 'bar',name = colnames(dist_data)[j]) %>%
layout( barmode = 'stack')
}
p
I am wondering whether there is something wrong in the loop.
When trying manually for adding trace1, works fine. When adding trace 2 (j=3), trace1's values become automatically equal to trace2's value.
UPD: When using dplyr, I have issues with some other parts of my code.
Is there a solution without it?
Thank you for the help,
You are overwriting p at each loop iteration. Try:
p = p %>% add_trace(y = ~as.numeric(dist_data[,j]), type = 'bar',name = colnames(dist_data)[j]) %>%
layout( barmode = 'stack')
2nd Edit:
not sure why this is happening. It works if you reshape to a long format dataframe which is better practice than using a for loop:
mtcars %>%
mutate(id = rownames(.)) %>%
gather(key = "variable",value = "value",-id) %>%
plot_ly(x = ~id, y=~value, type="bar", color=~variable) %>%
layout(barmode = "stack")
Edit:
dist_data=mtcars
p = plot_ly( x = rownames(dist_data),
y = as.numeric(dist_data[,1]),
type = 'bar', name = colnames(dist_data)[1]) %>%
layout(legend = list(x = 0.1, y = 0.9))
for ( j in 2:length(colnames(dist_data))){
p = add_trace(p, y = ~as.numeric(dist_data[,j]),
type = 'bar',name = colnames(dist_data)[j]) %>%
layout( barmode = 'stack')
}
p

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

R plotly show only labels where percentage value is value is above 10

I am making a pie-chart in plotly in R.
I want my labels to be on the chart, so I use textposition = "inside", and for the very small slices those values are not visible.
I am trying to find a way to exclude those labels.
Ideally, I would like to like to not print any lables on my plot that are below 10%.
Setting textposition = "auto" doesn't work well, since there are a lot of small slices, and it makes the graph look very messy.
Is there a way to do it?
For example these piecharts from plotly website (https://plot.ly/r/pie-charts/)
library(plotly)
library(dplyr)
cut <- diamonds %>%
group_by(cut) %>%
summarize(count = n())
color <- diamonds %>%
group_by(color) %>%
summarize(count = n())
clarity <- diamonds %>%
group_by(clarity) %>%
summarize(count = n())
plot_ly(cut, labels = cut, values = count, type = "pie", domain = list(x = c(0, 0.4), y = c(0.4, 1)),
name = "Cut", showlegend = F) %>%
add_trace(data = color, labels = color, values = count, type = "pie", domain = list(x = c(0.6, 1), y = c(0.4, 1)),
name = "Color", showlegend = F) %>%
add_trace(data = clarity, labels = clarity, values = count, type = "pie", domain = list(x = c(0.25, 0.75), y = c(0, 0.6)),
name = "Clarity", showlegend = F) %>%
layout(title = "Pie Charts with Subplots")
In the plot for Clarity 1.37% are outside of the plot, while I would like them not to show at all.
You'll have to specify sector labels manually like so:
# Sample data
df <- data.frame(category = LETTERS[1:10],
value = sample(1:50, size = 10))
# Create sector labels
pct <- round(df$value/sum(df$value),2)
pct[pct<0.1] <- 0 # Anything less than 10% should be blank
pct <- paste0(pct*100, "%")
pct[grep("0%", pct)] <- ""
# Install devtools
install.packages("devtools")
# Install latest version of plotly from github
devtools::install_github("ropensci/plotly")
# Plot
library(plotly)
plot_ly(df,
labels = ~category, # Note formula since plotly 4.0
values = ~value, # Note formula since plotly 4.0
type = "pie",
text = pct, # Manually specify sector labels
textposition = "inside",
textinfo = "text" # Ensure plotly only shows our labels and nothing else
)
Check out https://plot.ly/r/reference/#pie for more information...

Resources