I'm trying to use R plotly's bar type plot to generate a plot with horizontally laid out boxes and add to that a horizontal line which is in their background (rather than goes on top of them). In addition, I would like the line to extend symmetrically one box unit in each direction.
Here's what I'm doing:
plot.df <- data.frame(x = paste0("LONG NAME ",1:6),y = 0.2,width=0.75,group = c("A","B","B","B","C","A"),stringsAsFactors = F)
plot.df$group <- factor(plot.df$group)
plotly::plot_ly(plot.df) %>%
plotly::add_trace(x=~x,y=~y/2,type='scatter',mode='lines',line=list(color='black'),showlegend=F) %>%
plotly::add_bars(x=~x,y=~y,width=~width,color=~group) %>%
plotly::layout(xaxis=list(title=NA,zeroline=F,tickangle=45),yaxis=list(title=NA,zeroline=F,showgrid=F,range=c(0,1),showticklabels=F))
Which gives:
My questions are:
How to extend the the line in both directions
How to put the line in the background so it does not run over the boxes
I specified plot.df$y as 0.2 but the yaxis range to be c(0,1) so that the boxes don't look like long bars. But then the legend appears too high. Any better way to get square boxes with the legend appearing lower than it currently is?
For the horizontal line you can see Horizontal/Vertical Line in plotly
with
layout(legend =list(x = 1 ,y =0 ))
you can solve the legend problem
I could not solve your second point (put the bar in the background). I hope it helps:
hline <- function(y = 0, color = "blue") {
list(
type = "line",
x0 = 0,
x1 = 1,
xref = "paper",
y0 = y,
y1 = y,
line = list(color = color)
)
}
plot_ly(plot.df) %>%
add_bars(x=~x,y=~y,width=~width,color=~group, hoverinfo = "text") %>%
layout(shapes = list(hline(0.1)))%>%
layout(legend =list(x = 1 ,y =0 ))%>%
layout(xaxis=list(title=NA,zeroline=F,tickangle=45),yaxis=list(title=NA,zeroline=F,showgrid=F,range=c(0,1),showticklabels=F))
Related
I have a database df that has information of Covid effect for some countries in the world during January-July 2020.
Following the code in https://www.youtube.com/watch?v=RrtqBYLf404 I have created the following dynamic map.
library(plotly)
graph = plot_geo(df,
locationmode = "country-names",
frame = ~month) %>%
add_trace(locations = ~iso,
z = ~effect_covid_avg,
zmin = min(df$effect_covid_avg),
zmax = max(df$effect_covid_avg),
color = ~effect_covid_avg,
colorscale = 'Hot', #colorscale = 'heat', 'diverging', #colorscale = 'YlOrRd',
text = ~hover,
hoverinfo = 'text')
graph
However, I want to take screenshots of some months so I can include them into a static pdf file.
I want to make some modifications so to have:
Color of the palette (blue for positive, red for negative, whiter for 0). As you can see I have tried several palettes, not succesfully ('heat', 'diverging', 'YlOrRd').
Include the color legend inside the plot.
One of my screenshots looks like this.
Any clue?
Thank you
By modifying the zmin and zmax to the same value with different sign you locate 0 in the middle.
By changing "colorscale" to "colors" you can freely use the palettes. Therefore by applying "RdBu" you have the negatives in red and the positives in blue.
1 and 2 combined look like this:
graph = plot_geo(some_data_values,
locationmode = "country-names",
frame = ~month) %>%
add_trace(locations = ~iso,
z = ~effect_covid_avg,
zmin = -0.8, # below the min (so 0 is at the center of the palette)
zmax = 0.8, # over the max (so 0 is at the center of the palette)
color = ~effect_covid_avg,
colors = 'RdBu',
text = ~hover,
hoverinfo = 'text')
graph
Still have to solve how to put the legend in the plot?
I have a scatter plot with numeric values on both the axis. I want to add two draggable lines, one horizontal and one vertical. Also, I would like to change the color of points in the top-right quadrant formed by the two lines. I could not find any way to do this in R.
My question is similar to Horizontal/Vertical Line in plotly
Two things I want to add is
Ability to drag vertical and horizontal lines
Return values on which the two lines intersect the x and y axis, so that I can use those values as an input for another UI.
My code sample
data <- data.frame(y = sample(0:50, 100, replace = TRUE),
x = round(runif(100),2)
)
plot_ly(data, x = ~x, y = ~y)
(1) You can add draggable lines as follows:
plot_ly(data, x = ~x, y = ~y, type = 'scatter') %>%
layout(shapes = list(
#vertical line
list(type = "line", x0 = 0.4, x1 = 0.4,
y0 = 0, y1 = 1, yref = "paper"),
#horizontal line
list(type = "line", x0 = 0, x1 = 1,
y0 = 30, y1 = 30, xref = "paper"))) %>%
# allow to edit plot by dragging lines
config(edits = list(shapePosition = TRUE))
Similar to https://stackoverflow.com/a/54777145/5840900
(2) In an interactive environment, you can extract the values of the last dragged line with:
# Only within reactive shiny context
newData <- plotly::event_data("plotly_relayout")
Hopefully this is still helpful!
I am trying to produce a dumbell plot in R. In this case, there are four rows, and they need to have different and specific colors each. I define the colors as part of the dataset using colorRampPalette(). Then when I produce the plot, the colors get mixed in inappropriate ways. See the image below, and in particular the legend.
As you can see, the orange is supposed to be #7570B3 according to the legend. But this is not correct. The color 7570B3 is purple ! For this reason, the colors that I had defined in the dataset are mixed in the plot. "Alt 2" sound be in orange and "Alt 3" should be in purple.
Does anyone know how to fix this ? Any help would be very appreciated.
Here is a simple version of the code:
table_stats_scores <- data.frame(alt=c("alt1","alt2","alt3","alt4"),
average=c(15,20,10,5),
dumb_colors= colorRampPalette(brewer.pal(4,"Dark2"))(4),
min=c(10,15,5,0),max=c(20,25,15,10)
)
table_stats_scores # This is the dataset
table_stats_scores <- table_stats_scores[order(-
table_stats_scores$average),] # ordering
table_stats_scores$alt <- factor(table_stats_scores$alt,
levels = table_stats_scores$alt[order(table_stats_scores$average)])
# giving factor status to alternatives so that plot_ly() picks up on this
p <- plot_ly(table_stats_scores, x=table_stats_scores$average, color = ~
dumb_colors,
y=table_stats_scores$alt,text=table_stats_scores$alt) %>%
add_segments(x = ~min, xend = ~max, y = ~alt, yend = ~alt,name = "Min-Max
range", showlegend = FALSE, line = list(width = 4)) %>%
add_markers(x = ~average, y = ~alt, name = "Mean",
marker=list(size=8.5),showlegend = FALSE) %>%
add_text(textposition = "top right") %>%
layout(title = "Scores of alternatives",
xaxis = list(title = "scores"),
yaxis = list(title = "Alternatives")
)
p
Yes color can be an issue in plotly, because there are several ways to specify it, and the assignment order of the various elements from the dataframe can be hard to keep in sync.
The following changes were made:
added a list of brighter colors to your dataframe because I couldn't easily visualize the brewer.pal colors. Better to debug with something obvious.
changed the color parameter to the alt column, because it is really just used only indirectly to set the color, and mostly it determines the text in the legend.
added the colors to the text parameter (instead of alt) so I could see if it was assigning the colors correctly.
changed the sort order to the default "ascending" on the table_stat_scores sort because otherwise it assigned the colors in the incorrect order (don't completely understand this - seems like there is some mysterious sorting/re-ordering going on internally)
added a colors parameter to the add_segments and add_markers so that they set the color in the same way using the same column.
I think this gets you want you want:
library(plotly)
library(RColorBrewer)
table_stats_scores <- data.frame(alt=c("alt1","alt2","alt3","alt4"),
average=c(15,20,10,5),
dumb_colors= colorRampPalette(brewer.pal(4,"Dark2"))(4),
min=c(10,15,5,0),max=c(20,25,15,10)
)
table_stats_scores # This is the dataset
table_stats_scores$bright_colors <- c("#FF0000","#00FF00","#0000FF","#FF00FF")
table_stats_scores <- table_stats_scores[order(table_stats_scores$average),] # ordering
table_stats_scores$alt <- factor(table_stats_scores$alt,
levels = table_stats_scores$alt[order(table_stats_scores$average)])
# giving factor status to alternatives so that plot_ly() picks up on this
p <- plot_ly(table_stats_scores, x=~average, color = ~alt, y=~alt,text=~bright_colors) %>%
add_segments(x = ~min, xend = ~max, y = ~alt, yend = ~alt,name = "Min-Max range",
colors=~bright_colors, showlegend = FALSE, line = list(width = 4)) %>%
add_markers(x = ~average, y = ~alt, name = "Mean",
marker=list(size=8.5,colors=~bright_colors),showlegend = FALSE) %>%
add_text(textposition = "top right") %>%
layout(title = "Scores of alternatives",
xaxis = list(title = "scores"),
yaxis = list(title = "Alternatives")
)
p
yielding this:
I'm working with a proportional bar chart and I'd like to draw a vertical line at a particular X value. I'd prefer to accomplish this using the plotly package, but it doesn't seem to be easily done.
The solution found at Horizontal/Vertical Line in plotly doesn't seem to get the job done.
I've provided some sample code below that could be used to draw the vertical line at X = 3.
library(plotly)
library(ggplot2)
plot_ly(diamonds[1:1000, ], x = ~x, y = ~cut, color = ~color) %>% add_bars()
I'd appreciate any help in this matter.
I found some information about lines in plotly from Zappos Engineering here. The range -0.5 to 4.5 is because there are five categories in the data provided, each centered on a whole number. The y range creates the line, while the x constant (at 3) keeps the line vertical.
p <- plot_ly(diamonds[1:1000, ], x = ~x, y = ~cut, color = ~color) %>% add_bars()
p <- layout(p, shapes = list(type = "line", fillcolor = "red",
line = list(color = "red"),
opacity = 1,
x0 = 3, x1 = 3, xref = 'x',
y0 = -0.5, y1 = 4.5, yref = 'y'))
I am new to plotly and want to make my own bullet chart (a bit like http://bl.ocks.org/mbostock/4061961) that has markers/traces to show the values of the relevant values when comparing actual vs expected.
Below is my attempt:
q <- ggplot(data.frame(measure='',actual=25),aes(x=measure,y=actual))+
geom_bar(stat='identity')+
ylim(c(0,35))+
geom_hline(yintercept = 30,color='red')+
geom_text(y=30,label='Expected',angle=270,vjust=0)+
coord_flip()+
ylab('Num. of carrots')
q
q1 <- ggplotly(q) %>% add_markers()
q1
When converting it to plotly using ggplotly, the text looks like it has not rotated correctly, and the markers/traces do not show for the bar chart...Any help here would be much appreciated.
Kindest regards,
HLM
I do not think that plotly supports rotating text for type="scatter" (which is how ggplotly is interpreting your geom_text). You can delete the geom_text line from the ggplot graph, then add text to the plotly one using annotations:
q1 <- ggplotly(q) %>% add_markers() %>%
layout(annotations = list(x = 30, y = 1, text = "Expected", textangle=270))
q1
update
The 2nd part of your question (how to also get hover info on the bar) is slightly trickier. To get the hover info, we can create the bars using the plotly API directly like this
p.bars = plot_ly(data = data.frame(measure='', actual=25)) %>%
add_bars(y=~measure, x=~actual, orientation="h")
we can add the text annotation to it like this
p.bars.text = p.bars %>%
layout(annotations = list(x = 30, y = 0, text = "Expected", textangle=270,
showarrow=F, xanchor="center"))
But the problem is that adding a line also to this plot by
p.bars.text %>% add_segments(x=30, xend=30, y=-0.5, yend=0.5)
gives an error
Error in populate_categorical_axes(p) : Can't display both discrete & non-discrete data on same axis
I.e. we can only specify the y values of the line with respect to categorical values of y. So, for example we can do
dat1 = data.frame(measure=letters[1:2], actual=c(25,20))
plot_ly(data = dat1) %>%
add_bars(y=~measure, x=~actual, orientation="h") %>%
layout(annotations = list(x = 29, y = 0, text = "Expected", textangle=270,
showarrow=F, xanchor="center")) %>%
add_segments(x=30, xend=30, y='a', yend='b')
which gives the following in which the line is aligned with the category labels rather than with the width of the bars
The only solution I have to this at the moment is to use a numeric axis for the categories, and then set the axis labels using ticktext:
plot_ly(data = data.frame(measure=c(0,1), actual=c(25,20))) %>%
add_bars(y=~measure, x=~actual, orientation="h", showlegend=F) %>%
add_segments(x=30, xend=30, y=-0.4, yend=0.4, showlegend=F) %>%
layout(annotations = list(x = 29.5, y = 0, text = "Expected", textangle=270, showarrow=F, xanchor="center"),
yaxis = list(tickmode="array", tickvals=c(0,1), ticktext=c("", "") ))