I'm using the plotly package in R to build an R Shiny dashboard. I want to order my pie chart in a custom order (non-alphabetic, non-descending/ascending order). For some reason I can't find how to achieve this.
Help would be highly appreciated!
# Get Manufacturer
mtcars$manuf <- sapply(strsplit(rownames(mtcars), " "), "[[", 1)
df <- mtcars %>%
group_by(manuf) %>%
summarize(count = n())
# Create custom order
customOrder <- c(df$manuf[12:22],df$manuf[1:11])
# Order data frame
df <- df %>% slice(match(customOrder, manuf))
# Create factor
df$manuf <- factor(df$manuf, levels = df[["manuf"]])
# Plot
df %>% plot_ly(labels = ~manuf, values = ~count) %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
Ok, the answer is apparently twofold. Firstly, there is an argument in plot_ly, asking to sort the data on values (default is TRUE) or work with the custom order. Change this to FALSE.
Then, secondly, the order (clockwise) is different from the order in the data frame. The pie starts in the top right corner, and continues counterclockwise.
Hence, the following solves the problem:
# Get Manufacturer
mtcars$manuf <- sapply(strsplit(rownames(mtcars), " "), "[[", 1)
df <- mtcars %>%
group_by(manuf) %>%
summarize(count = n())
# Create custom order
customOrder <- c(df$manuf[12:22],df$manuf[1:11])
# Adjust customOrder to deal with pie
customOrder <- c(customOrder[1],rev(customOrder[2:length(customOrder)]))
# Order data frame
df <- df %>% slice(match(customOrder, manuf))
# Create factor
df$manuf <- factor(df$manuf, levels = df[["manuf"]])
# Plot
df %>% plot_ly(labels = ~manuf, values = ~count, sort = FALSE) %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
Related
I'm struggeling on a simple task. I have a database with 3 columns :
Year (numeric)
Age (numeric)
Pop (numeric)
Part60 : The % of individuals with age >= 60 (string like '% of poeple over 60 : 12%'). This value is the same for each rows of a year.
Dataset looks like :
I built a plotly bargraph with a frame based on the year. So I have a slider which allow me to show for each age the number of individuals and this is animated year by year.
I would like to add an anotation which shows the value of Part60 for the year of the frame... I know that it's possible with a ggplot sent to ggplotly function, however I want to do it from scratch with a plot_ly function as parameters are (for me) easier to control and follow the logic of my code.
This is my code :
gH <- plot_ly(data = dataH,
name = 'Hommes',
marker = list(color = ispfPalette[4]),
x = ~Pop,
y = ~Age,
frame = ~Annee)
gH <- gH %>% layout(yaxis = list(categoryorder="array",
categoryarray=dataH$Age))
gH <- gH %>% layout(yaxis = list(title = '',
zeroline = TRUE,
showline = TRUE,
showticklabels = TRUE,
showgrid = FALSE),
xaxis = list(title = '',
zeroline = TRUE,
showline = TRUE,
autorange = "reversed"),
shapes = hline(60))
gH <- gH %>% add_annotations(
x = 3000,
y = 62,
text = 'Part des 60 ans et + : 12 %',
showarrow = F,
color = ispfPalette[8]
Where text = 'Part des 60 ans et + : 12 %' should be replaced by something which allow me to get the value which belongs to the year of the slider.
Is someone may help me to do it ?
Thanks in advance for your great help.
Since I don't have your data, it's pretty difficult to give you the best answer. Although, here is a method in which you can add text that changes throughout the animation.
library(plotly)
library(tidyverse)
data(gapminder, package = "gapminder")
str(gapminder)
funModeling::df_status(gapminder)
# continent, lifeExp, year
gap <- gapminder %>% group_by(year, continent) %>%
summarise(Expectancy = mean(lifeExp))
# plot
p1 <- plot_ly(gap, x = ~Expectancy, y = ~continent,
frame = ~year, type = 'bar',
showlegend = F,
hovertemplate = paste0("Continent: %{y}<br>",
"<extra></extra>"),
texttemplate = "Life Expectancy: %{x:.2f}") %>%
layout(yaxis=list(title=""),
xaxis=list(title="Average Life Expectancy per Continent By Year"),
title=list(text=paste("Fancy Title")),
margin = list(t = 100))
p1
If you had text you wanted to animate that is not connected to each marker (bar, point, line), then you could do it this way.
# Something to add in the annotation text
gap2 <- gap %>% filter(continent == "Asia") %>%
droplevels() %>%
arrange(year)
# build to see frames
p2 <- plotly_build(p1)
# modify frames; need an annotation for each frame
# make sure the data is in order by year (order by frame)
lapply(1:nrow(gap2), # for each frame
function(i){
annotation = list(
data = gap2,
type = "text",
x = 77,
y = .5,
yref = "paper",
showarrow = F,
text = paste0("Asian Life Expectancy<br>",
sprintf("%.2f", gap2[i, ]$Expectancy)),
font = list(color = "#b21e29", size = 16))
p2$x$frames[[i]]$layout <<- list(annotations = list(annotation)) # change plot
})
p2
If anything is unclear, let me know.
I have a simple line chart, but some categories do not have all periods (xAxis), so the xAxis is not ordered at the end.
That is an example data:
The chart looks like that (with "2019-01" and "2019-03" exchanged)
Example Code
df <- data.frame(PERIODO = c("2017-01","2017-03","2018-01","2018-03",
"2018-03","2019-01",rep("2019-03",2),
"2020-01"),
CATEGORIA = c(rep("A",4),rep("B",2),"A","B","B"),
FRECUENCIA = c(2,3,3,1,2,4,1,1,2))
highchart() %>%
hc_xAxis(type = "category") %>%
hc_add_series(df, "line",
hcaes(x = PERIODO, y = FRECUENCIA,
group = CATEGORIA),
dataLabels = list(enabled = TRUE,
style = list(fontSize = '13px'))
) %>%
hc_legend(enabled = TRUE, align = "right",layout = 'vertical',verticalAlign= "middle") %>%
hc_tooltip(shared = TRUE, crosshairs = TRUE
,style = list(fontSize = "18px")
Someone knows about how to keep the xAxis order by PERIODO: 2017-01,2017-03,2018-01,2018-03,2019-01,2019-03,2020-01
Perhaps you can put your dates PERIODO in Date format (use first day of the month if you only have months).
df$PERIODO <- as.Date(paste0(df$PERIODO, "-01"))
Then, use type = "datetime" instead of category for your hc_xAxis argument. You can indicate what you want as labels on your x-axis using dateTimeLabelFormats.
highchart() %>%
hc_xAxis(type = "datetime",
dateTimeLabelFormats = list(month = '%b %Y')) %>%
...
Default labels and more information can be found here.
I'm new to plotly, trying to figure out how to get a piechart to be aligned at the center of the entire plot area.
library(dplyr)
library(plotly)
data_for_plot <-
mtcars %>%
count(cyl)
> data_for_plot
## cyl n
## 1 4 11
## 2 6 7
## 3 8 14
plot_ly(data_for_plot, labels = ~cyl, values = ~n, type = 'pie', hole = 0.05 ,textposition = 'outside',textinfo = 'percent') %>%
layout(title = list(text = "my nice title is here", xanchor = "center"),
showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = TRUE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = TRUE)) %>%
layout(paper_bgcolor = "pink")
So I get this pie chart, which is not centered:
I assume that inside layout() I need something that refers to the piechart itself, to assign it with xanchor = "center". But I researched this and couldn't find an answer.
Update on my attempts - 2020-01-18
I've tested the majority of attributes in layout() and still couldn't find something that would work with xanchor = "center". I've alse examined plotly's reference guide but so far to no avail.
Seems that the solution involves setting up the margin attribute within layout(). The solution is based on this hint, referring to this post. Implementing this to R is done using the following code:
plot_ly(data_for_plot, labels = ~cyl, values = ~n, type = 'pie', hole = 0.05 ,textposition = 'outside',textinfo = 'percent') %>%
layout(title = list(text = "my nice title is here", xanchor = "center"),
showlegend = F,
margin = list(l = 20, r = 20),
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = TRUE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = TRUE)) %>%
layout(paper_bgcolor = "pink")
I posted this in the plotly community forum but got absolutely no activity! Hope you can help here:
I have map time-series data, some countries don’t have data and plotly does not plot them at all. I can have them outlined and they look different but it appears nowhere that the data is missing there (i.e. I want a legend entry). How can I achieve this? Here is a reprex:
library(plotly)
library(dplyr)
data = read.csv('https://github.com/lc5415/COVID19/raw/master/data.csv')
l <- list(color = toRGB("grey"), width = 0.5)
g <- list(
scope = 'world',
countrycolor = toRGB('grey'),
showframe = T,
showcoastlines = TRUE,
projection = list(type = 'natural earth')
)
map.time = data %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code, marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
map.time
Note that the countries with missing data (e.g. Russia) have as many data points as all other countries, the issue is not that they do not appear in the dtaframe passed to plotly.
The obvious way to handle this is to create a separate labels column for the tooltip that reads "No data" for NA values (with the actual value otherwise), then make your actual NA values 0. This will give a uniform appearance to all the countries but correctly tells you when a country has no data.
map.time = data %>%
mutate_if(is.numeric, function(x) {x[is.na(x)] <- -1; x}) %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code,
marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
Which gives:
I'm using the plotly package in R to build an R Shiny dashboard. I want to order my pie chart in a custom order (non-alphabetic, non-descending/ascending order). For some reason I can't find how to achieve this.
Help would be highly appreciated!
# Get Manufacturer
mtcars$manuf <- sapply(strsplit(rownames(mtcars), " "), "[[", 1)
df <- mtcars %>%
group_by(manuf) %>%
summarize(count = n())
# Create custom order
customOrder <- c(df$manuf[12:22],df$manuf[1:11])
# Order data frame
df <- df %>% slice(match(customOrder, manuf))
# Create factor
df$manuf <- factor(df$manuf, levels = df[["manuf"]])
# Plot
df %>% plot_ly(labels = ~manuf, values = ~count) %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
Ok, the answer is apparently twofold. Firstly, there is an argument in plot_ly, asking to sort the data on values (default is TRUE) or work with the custom order. Change this to FALSE.
Then, secondly, the order (clockwise) is different from the order in the data frame. The pie starts in the top right corner, and continues counterclockwise.
Hence, the following solves the problem:
# Get Manufacturer
mtcars$manuf <- sapply(strsplit(rownames(mtcars), " "), "[[", 1)
df <- mtcars %>%
group_by(manuf) %>%
summarize(count = n())
# Create custom order
customOrder <- c(df$manuf[12:22],df$manuf[1:11])
# Adjust customOrder to deal with pie
customOrder <- c(customOrder[1],rev(customOrder[2:length(customOrder)]))
# Order data frame
df <- df %>% slice(match(customOrder, manuf))
# Create factor
df$manuf <- factor(df$manuf, levels = df[["manuf"]])
# Plot
df %>% plot_ly(labels = ~manuf, values = ~count, sort = FALSE) %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))