Change format of y axis in plotly - r

I'm trying to format y axis numbers' format (in plotly) and - after hours of googling - I've decieded to ask here.
I've got a plot like here:
generated with this code:
library("plotly")
library("dplyr")
data.frame(miesiac_label = as.character(as.roman(c(1:12))),
ile = c(12000, 12100, 11100, 12000, 12000, 11900, 12200, 12100, 6000, 12100, 12100, 12100)) -> dane
dane$miesiac_label <- factor(dane$miesiac_label, levels = dane[["miesiac_label"]])
plot_ly(dane) %>%
add_trace(x = ~miesiac_label, y = ~ile,
type = 'bar', marker = list(color = '#99d3df'))
My goal is to change yaxis formatting from 12k, 10k, 8k, ... to more "polish one", so 12 tys, 10 tys, 8 tys, .... I know how to change it setting ticktext and ticktext, but I don't want to set values on my own, I prefer to have them more automatic.
I've read about thickformat but I didn't find there option, which would change k to tys.
Thanks for your help!

I think using layout() gives you what you want. First, you need to divide your y by 1000 (maybe there is another way) and then use ticksuffix to add tys.
plot_ly(dane) %>%
add_trace(x = ~miesiac_label, y = ~ile/1000, type = 'bar', marker = list(color = '#99d3df')) %>%
layout(yaxis = list(ticksuffix= "tys", title = "ile"))

Related

Why is hovertemplate not showing up correctly for some data points for plotly in R

mydat2 <- data.frame(subject = c("math", "english", "chemistry"), score = c(80, 50, 65), class = c("A", "B", "A"), count = c(50, 60, 70))
library(plotly)
plot_ly(data = mydat2,
x = ~score,
y = ~count,
color = ~class,
customdata= ~class,
hoverinfo = 'text',
text = ~subject,
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"%{yaxis.title.text}: %{y:,.0f}<br>",
"%{xaxis.title.text}: %{x:,.0f}<br>",
"Class: %{customdata}",
"<extra></extra>"
))
I'm confused as to why the hover for the left most point shows up as %{text} instead of english. The hover labels for the other 2 points on the plot are perfectly fine.
Here is your graph, with the hover template that you're looking for. The explanation follows.
plot_ly(data = mydat2,
x = ~score,
y = ~count,
color = ~class,
type = "scatter",
mode = "markers",
customdata= ~class,
hoverinfo = 'text',
text = ~I(subject), # <---- I changed!!
hovertemplate = paste(
"<b>%{text}</b><br><br>",
"%{yaxis.title.text}: %{y:,.0f}<br>",
"%{xaxis.title.text}: %{x:,.0f}<br>",
"Class: %{customdata}",
"<extra></extra>"
))
I've seen this problem before. I've usually come up with a workaround, but never really figured out what went wrong until now. I found a closed ticket on GitHub for this issue (closed in 2019). (Ah, ya... so not fixed.) Apparently, it has to do with using color.
However, the bright spot...for a hot minute someone actually believed it was a problem and came up with a fix. #cpsievert wrote a bit of code that includes an lapply call (towards the middle of the page, if you visit the site). When I investigated what the code did, I realized it could be a lot simpler (and it was pretty simple, to begin with).
That ticket on GitHub is here if you wanted to check that out.
This is the code the maintainer provided (that you don't actually need).
l <- plotly_build(p)$x
l$data <- lapply(l$data, function(tr) { tr[["text"]] <- I(tr[["text"]]); tr })
as_widget(l)
The fix is the function I(). Instead of hovertext = or text = ~subject, you need hovertext = or text = ~I(subject). <-- note the I()

How to show only some hoverinfo points on a line graph with Plotly in R

I have traffic and article dfs as follows:
library(plotly)
library(dplyr)
set.seed(101)
traffic <- data.frame(Date = seq(as.Date("2021-06-01"), as.Date("2021-07-10"), by="days"),
Views = round(rnorm(40, 5000, 200),0))
articleData <- data.frame(Date = as.Date(c("2021-06-01", "2021-07-04", "2021-07-10")),
article = c("Article 1", "Article 2", "Article 3"))
joinedData <- left_join(traffic, articleData)
I want to make a plotly line graph that shows a line for traffic, but for the 3 dates where there were articles published I would like to add a dot that the person can cover over and it will show what article was published that day. Below is what I was able to put together:
plot_ly(data = joinedData, x = ~Date, y = ~Views, type = "scatter", mode = "lines") %>%
add_trace(hoverinfo = "text", text = ~article, mode = "markers")
This technically works, but it puts a marker on every single day, not just the 3 days that had articles. Is there a way to ignore marking the days that don't have articles? I really just want to draw attention to the days that have articles published and show whether that article shows a spike in traffic or not.
I think you were really close in your question. I think you just need to filter your data for those three articles and create a new dataframe. You can use the new dataset in add_trace. This will only put points on the dates that had articles published.
library(dplyr)
library(plotly)
filteredJoinedData <- joinedData %>%
filter(article != "NA")
plot_ly(data = joinedData, x = ~Date, y = ~Views, type = "scatter", mode = "lines") %>%
add_trace(data = filteredJoinedData, hoverinfo = "text", text = ~article, mode = "markers")
Giving you this graph

Multiple y-axes in shiny app w/ highcharter

I'm trying to render a graph in a shiny app using highcharter that shares an x-axis (days) but has multiple y-axes (a percent and a count). After some research it seems like I should use the 'hc_yAxis_multiples' method. On the left y-axis, I have % displayed. On the right y-axis, I want the count displayed. There is a line graph that is based on the left y-axis (%), and a stacked bar graph that is displayed based on the right y-axis.
I have been able to overlay the two graphs, but the bar chart portion based on the right y-axis is not formatted to the corresponding y-axis. Based on what I have been looking at, it seems like something like this would produce a result that I want:
##This first block is to show what the data types of the variables I'm using are and what the structure of my df looks like
df$inbox_rate <- df$total_inbox / df$total_volume
df$inbox_rate <- round((df$inbox_rate*100),0)
df$received_dt <- as.character(df$received_dt)
df$received_dt <- as.Date(df$received_dt, "%Y%m%d")
df <- df[order(df$received_dt),]
## This second block here is where I'm trying to build the chart with two Y-axes
hc <- highchart()%>%
hc_title(text = paste(domain_name,sep=""),align = "center") %>%
hc_legend(align = "center") %>%
hc_xAxis(type = "datetime", labels = list(format = '{value:%m/%d}')) %>%
hc_yAxis_multiples(list(title = list(text = "IPR"),labels=list(format = '{value}%'),min=0,
max=100,showFirstLabel = TRUE,showLastLabel=TRUE,opposite = FALSE),
list(title = list(text = "Total Subscribers"),min=0,max = max(df$total_users),
labels = list(format = "{value}"),showLastLabel = FALSE, opposite = TRUE)) %>%
hc_plotOptions(column = list(stacking = "normal")) %>%
hc_add_series(df,"column",hcaes(
x=received_dt,y=total_users,group=isp,yAxis=total_users)) %>%
hc_add_series(df,type="line",hcaes(
x=received_dt,y=inbox_rate,group=isp,yAxis=inbox_rate)) %>%
hc_exporting(enabled = TRUE) %>%
hc_add_theme(thm)
hc
However this produces something that looks like this.
To give more insight about the data I'm using, the domain_name is a string variable that looks like this: example.com. The total_users variable is a number that varies from 0 to about 50000. The received_dt variable is a date, formatted using as.Date(df$received_dt, "%Y%m%d"). The inbox_rate variable is a percent, from 0 to 100.
The bar counts are all displaying to the full height of the graph, even though the values of the bars vary widely. To reiterate, I want the right y-axis that the bar chart heights are based on to be the count of the df$total_users. Within the hc_yAxis_multiples function, there are two lists given. I thought that the first list gives the left y-axis, and the second gives the right. The closest answer to my question that I could find was given by this stackoverflow response
If anyone has any insight, it would be very much appreciated!
Your use of the yAxis statement in hc_add_series seems to be off. First, it should not be inside hcaes and second, it's a number specifying which axis (in order of appearance in hy_yAxis_multiple call) the series belongs to. So hc_add_series(..., yAxis = 1) should be used to assign a series to the second (right) axis.
Below is a (fully self-explaining, independent, minimal) example that shows how it should work.
library(highcharter)
df <- data.frame(
total_inbox = c(2, 3, 4, 5, 6),
total_volume = c(30, 30, 30, 30, 30),
total_users = c(300, 400, 20, 340, 330),
received_dt = c("20180202", "20180204", "20180206", "20180210", "20180212"),
isp = "ProviderXY"
)
df$inbox_rate <- df$total_inbox / df$total_volume
df$inbox_rate <- round((df$inbox_rate*100),0)
df$received_dt <- as.character(df$received_dt)
df$received_dt <- as.Date(df$received_dt, "%Y%m%d")
df <- df[order(df$received_dt),]
hc <- highchart()%>%
hc_xAxis(type = "datetime", labels = list(format = '{value:%m/%d}')) %>%
hc_yAxis_multiples(list(title = list(text = "IPR"),labels=list(format = '{value}%'),min=0,
max=100,showFirstLabel = TRUE,showLastLabel=TRUE,opposite = FALSE),
list(title = list(text = "Total Subscribers"),min=0,max = max(df$total_users),
labels = list(format = "{value}"),showLastLabel = FALSE, opposite = TRUE)) %>%
hc_plotOptions(column = list(stacking = "normal")) %>%
hc_add_series(df,type="column",hcaes(x=received_dt,y=total_users,group=isp),yAxis=1) %>%
hc_add_series(df,type="line",hcaes(x=received_dt,y=inbox_rate,group=isp))
hc
Maybe take this as an example how code in questions should be like. Copy-Paste-Runnable, no outside variables and minus all the things that dont matter here (like the theme and legend for example).

plotly in R: adding labels to surface area charts through layout?

I'm working with surface area charts in plotly and I'm wondering how to change the labels as the process seems different from flat charts so I'm having trouble wrapping my head around how they layout should be arranged. I'm getting a warning message but I see that the title label has gone through, wondering how to get the X axis and Y axis to change. Below is my reproducible code using he built in data set freeny:
#stack question for surface plot
library(plotly)
library(zoo)
#set data
master = freeny
master$year = round(as.numeric(row.names(master)))
master$month = sample(1:6, 39, replace=TRUE)
master$month = paste0("0",master$month)
master$date = as.Date(with(master, paste0(year,"-" ,month,"-" ,"28")))
master$weekday = weekdays(master$date)
master$month_year = as.yearmon(master$date)
master
#build matrix
matrix_d = xtabs(income.level ~ month_year + weekday, master)
matrix_d
#plot
p = plot_ly(z = ~matrix_d) %>% add_surface()
p
#label
p = layout(p, # all of layout's properties: /r/reference/#layout
title = "income levels across month and weekdays", # layout's title: /r/reference/#layout-title
xaxis = list( # layout's xaxis is a named list. List of valid keys: /r/reference/#layout-xaxis
title = "weekday", # xaxis's title: /r/reference/#layout-xaxis-title
showgrid = F # xaxis's showgrid: /r/reference/#layout-xaxis-showgrid
),
yaxis = list( # layout's yaxis is a named list. List of valid keys: /r/reference/#layout-yaxis
title = "month_year" # yaxis's title: /r/reference/#layout-yaxis-title
),
zaxis = list(
title = "income_level"
))
p
Warning message:
'layout' objects don't have these attributes: 'zaxis'
Valid attributes include:
'font', 'title', 'titlefont', 'autosize', 'width', 'height', 'margin', 'paper_bgcolor', 'plot_bgcolor', 'separators', 'hidesources', 'smith', 'showlegend', 'dragmode', 'hovermode', 'xaxis', 'yaxis', 'scene', 'geo', 'legend', 'annotations', 'shapes', 'images', 'updatemenus', 'ternary', 'mapbox', 'radialaxis', 'angularaxis', 'direction', 'orientation', 'barmode', 'bargap', 'mapType'
EDIT FOLLOWUP:
Posted the answer below to the top question but as a followup how would I add values to the tick marks? I'm assuming there is a way to feed a list vector of ordinal values to the ticks such as c("0" = "sunday", "1" = "Monday" . . . ). Is this accurate?
Appreciate the help!!!
Found the answer from a different posting in case anyone ever needs it. I'm wondering though how to add the specific month and weekday to the tick marks?
p <- plot_ly(z = ~matrix_d) %>% add_surface() %>%
layout(title = 'income levels across month and weekdays',
scene = list(xaxis = list(title = 'weekday'),
yaxis = list(title = 'month'),
zaxis = list(title = 'income_level')))
p

Shiny with plotly

I'm creating a notebook with shiny and i have found the following issue when using the add-on plotly:
Data_xts=Data_xts() #this return a reactive data.frame. fm_timeseries is already formated as POSIXct and has the following format : YYYY-MM-DD hh:mm:ss
plot_ly(x=Data_xts$fm_timeseries, y = Data_xts$Open,name='Stock Prices',showlegend = FALSE) %>%
add_trace(x=Data_xts$fm_timeseries, y = Data_xts$UKX_open, yaxis='y2') %>%
add_trace(x=Data_xts$fm_timeseries, y = Data_xts$TotalNews, yaxis='y3') %>%
layout(yaxis=list(title='Stock Price'),
yaxis2=list(title='Market Index', overlaying = "y",side='right',position=.97,tickfont = list(size = 8)),
yaxis3=list(title='Total News', overlaying = "y",side='right',anchor='free', tickfont = list(size = 8),position=1),
xaxis=list(title='Time Series') , showlegend = TRUE)
Here is a couple of issues I'm founding:
Time stamp don't show as timestamp (I even tried the simple example from plotly and R and verified that it doesn't work on Shiny). In fact timestamp is categorize as string and the xaxis tittle can't be seen as a result of this.
Challenges getting the yaxis2 and 3 in the same axes without overlapping with the chart itself.
To solve this wonder if there is a format that we can pass into the xaxis (tried type='date' but didn't work) and if there is any type of auto-arrange on the yaxis on the right (2 and 3).
Try using "factor".
So in your example:
plot_ly(x= ~factor(Data_xts$fm_timeseries), y = ~Data_xts$Open, name='Stock Prices',showlegend = FALSE)

Resources