Add average line/plot line to area highchart R - r

I know there are a few similar questions to this out there but they all seem to use javascript (?) or something besides the normal R coding so I don't know how to use it in my code... anyways all I want to do is add a plotline to my area chart that shows the average of the values, how do I do that? I know that highcharter itself can not calculate the average so I can do that myself but how do I create the plotline .... thank you so much. (i tried to make the code so that it is easily 'reproducible' ? hope it is ok). I attached a picture of the current chart if that helps.
library(tidyverse)
library(highcharter)
library(ggplot2)
data("diamonds", package = "ggplot2")
df <- diamonds %>%
group_by(cut)%>%
count()
head(df, 4)
# Create chart
hc <- df %>%
hchart(
'area', hcaes(x = cut, y = n),
color = "lightblue"
) %>%
hc_yAxis(title = list(text = "cut"))
# Display chart
hc

Below is a mini example of using the highcharts widget. You can add each series using hc_add_series. In this case, we have two series and two y-axes. Using two y-axes helps to differentiate between the series. I'm not sure what values you're trying to calculate the average so I chose price.
Hope this helps add some clarity to highcharter!
library(tidyverse)
library(highcharter)
df <- diamonds %>%
group_by(cut)%>%
summarise(
n = n(),
avg_price = round(mean(price),2)
)
# create hc widget
highchart(type = "chart") %>%
# add both series
hc_add_series(df, hcaes(x = cut, y = n), color = "lightblue", yAxis = 0, type = "area", name = "N") %>%
hc_add_series(df, hcaes(x = cut, y = avg_price), yAxis = 1, type = "line", name = "Avg Price") %>%
# set type to categories since we're looking at categorical data
hc_xAxis(type = "category", categories = df$cut) %>%
hc_title(text = "Cut Freq vs Avg Price") %>%
# add each y-axis which is linked above in 'hc_add_series'
hc_yAxis_multiples(
list(title = list(text = "Cut")), # yAxis = 0
list(title = list(text = "Average Price"), opposite = TRUE) # yAxis = 1
) %>%
hc_tooltip(shared = TRUE, split = FALSE)
Ex:

Haha I got it. basically just this.
plotline <- list(
color = "red", value = mean(diamonds$cut), width = 2, zIndex = 5
)
hc_yAxis(plotLines = list(plotline))

Related

Highlight a certain candle in candlestick chart

I'm learning how to write code for different kinds of charts in R using plotly library. For example:
library(plotly)
library(quantmod)
getSymbols("AAPL",src='yahoo')
# basic example of ohlc charts
df <- data.frame(Date=index(AAPL),coredata(AAPL))
df <- tail(df, 30)
maxi_dif <- as.integer(which (df$diff == max(df$diff)))
maxi_x <- df[maxi_dif,'Date']
maxi_y <- df[maxi_dif,'diff']
fig <- df %>% plot_ly(x = ~Date, type="candlestick",
open = ~AAPL.Open, close = ~AAPL.Close,
high = ~AAPL.High, low = ~AAPL.Low)
There are different kinds of options of how to add legend,hovertext and etc on the plot. I wonder if it's possible to highlight certain candle in the chart? For example based on what candle is the longest/shortest in the data? I'm not very experienced in how these charts work, I only know the basics, so maybe the question is not applicable.
Example of what I want to achieve is in the attached image
image
Add a new trace with filtered data:
fig <- df %>% plot_ly(
x = ~ Date,
type = "candlestick",
open = ~ AAPL.Open,
close = ~ AAPL.Close,
high = ~ AAPL.High,
low = ~ AAPL.Low
) %>%
add_trace(
data = df %>% filter(Date == "2022-01-28"),
x = ~ Date,
type = "candlestick",
open = ~ AAPL.Open,
close = ~ AAPL.Close,
high = ~ AAPL.High,
low = ~ AAPL.Low,
increasing = list(fillcolor = "Blue", line = list(color = "Blue")),
decreasing = list(fillcolors = "Blue", line = list(color = "Blue")),
showlegend = FALSE
)
fig

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

Plotly bars with x-axis offset for timestamps

I want to plot some timestamps with plotly bars, with 1 bar indicating a whole hour.
My problem is that the ticks are centered in the middle and I would like to shift them to the left end of the bars.
When the plot isn't zoomed in, it's not such a problem, but when zooming in, more tick-labels will appear and they would be wrong.
EDIT: I need the option barmode = 'overlay' as I also have other traces to plot, which are not included in this example.
The picture below illustrates my current and exptected layout and here's some data to make that plot. (Some option I tried without success are also included in the xaxis configuration but uncommented).
library(plotly)
library(lubridate)
df <- data.frame(
ts = seq(as.POSIXct("2019-03-20 00:00:00"), by = "hour", length.out = 24),
val = sample(1:100, 24)
)
plot_ly() %>%
add_bars(data = df, x = ~ts, y = ~val) %>%
layout(dragmode = "select", autosize = TRUE, selectdirection = "h",
barmode = 'overlay',
bargap = 0.05,
xaxis = list(ticks = "outside",
type = "date",
# tickson="boundaries",
# offset=1800,
tickmode = "auto",
title = ""
)) %>%
config(scrollZoom = TRUE)
Would the following meet your needs?
One of the things that I take advantage of sometimes with plotly is that you can show different values in text that are independent of your the x and y values used to plot the data.
In this case, we can create a column with an offset time value, ts_x and plot the x values a half hour past the time for each row -- If you have a column for every hour, this effectively left-aligns the bars.
library(plotly)
df <- data.frame(
ts = seq(as.POSIXct("2019-03-20 00:00:00"), by = "hour", length.out = 24),
val = sample(1:100, 24)
)
## Create a dummy column with x offset values
df$ts_x <- df$ts + 1800
plot_ly() %>%
## Plot based on the dummy column
add_bars(data = df, x = ~ts_x, y = ~val,
## Cover up our tracks by not showing true x value on hoverinfo
hoverinfo = "text",
## Give text that includes the un-altered time values
text = ~paste0("Time: ",format(ts, format = "%B %d, %Y %H:%M"),
"<br>Value: ",val)) %>%
layout(dragmode = "select", autosize = TRUE, selectdirection = "h",
barmode = 'overlay',
bargap = 0.05,
xaxis = list(ticks = "outside",
type = "date",
tickmode = "auto",
title = ""
)) %>%
config(scrollZoom = TRUE)
By default, bars are centered, I didn't find how to change this.
One alternative is to add a second bar, because when there are 2 bars for each x-axis unity, one bar is at the left of the axis tick, and the second at the right (what you are trying to obtain with one bar).
Why not creating a second invisible bar ? :)
df <- data.frame(
ts = seq(as.POSIXct("2019-03-20 00:00:00"), by = "hour", length.out = 24),
val = sample(1:100, 24),
val0 = 0
)
plot_ly(df, type = 'bar') %>%
add_trace(x = ~ts, y = ~val0) %>%
add_trace(x = ~ts, y = ~val) %>%
layout(
showlegend = FALSE
) %>%
config(scrollZoom = TRUE)
This will create a legend (as there are 2 kind of bars, ones for val and ones for val0), so I removed it.
Are you sure you are not over engineering? Subtracting 30 minutes gives me a nice graph when zooming in.
I'm not suggest you actually edit the data, even if it's what I'm doing in the code. A small function in the call to add bars could solve it? If you overlay other data it could make a mess but I just wanted to suggest it.
library(plotly)
library(lubridate)
df2 <- data.frame(
ts = seq(as.POSIXct("2019-03-20 00:00:00"), by = "hour", length.out = 24) - minutes(30),
val = sample(1:100, 24)
)
plot_ly() %>%
add_bars(data = df2, x = ~ts, y = ~val) %>%
layout(dragmode = "select", autosize = TRUE, selectdirection = "h",
barmode = 'overlay',
bargap = 0.05,
xaxis = list(ticks = "outside",
type = "date",
# tickson="boundaries",
# offset=1800,
tickmode = "auto",
title = ""
)) %>%
config(scrollZoom = TRUE)

Is there a way to plot a scatter plot in highcharter with "jitter", like in ggplot2?

My doubt is exactly how is written in the title. I am trying to replicate a chart like the one that follows:
My point is that I need to use highcharter package. So, what I got for while is this:
hcboxplot(x = iris$Sepal.Length,
var = iris$Species,
outliers = FALSE) %>%
hc_chart(type = "column") %>% # to put box vertical
hc_size(width = NULL, height = 350) %>%
hc_add_series(
data = iris,
type = "scatter",
hcaes(x = "Species", y = "Sepal.Length", group = "Species")
)
I want to "jitter" the scatter, like in ggplot2.
Thanks in advance.
Wlademir.

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