I'm trying to draw a time series boxplot in R with the plotly libraries, however I need to be able to have total control of the ymin, ymax, ylow etc.
It renders perfectly fine in ggplot2, althought with a ton of warnings. It fails to render in ggplotly
Here is what I have.
msft = read.csv("http://ichart.finance.yahoo.com/table.csv?s=MSFT",
header=TRUE,
sep=",")
msft$Date
msftF = msft %>% tbl_df() %>% filter(as.Date(Date) > as.Date("2016-01-01")) %>% na.omit()
msftF %>%
ggplot(aes(x = factor(Date), ymin = Low, lower = Open, middle = Close, upper = Close, ymax = High)) +
geom_boxplot() +
geom_boxplot(stat = "identity")
#David Crook here's a simple example.
library(plotly)
library(quantmod)
prices <- getSymbols("MSFT", auto.assign = F)
prices <- prices[index(prices) >= "2016-01-01"]
# Make dataframe
prices <- data.frame(time = index(prices),
open = as.numeric(prices[,1]),
high = as.numeric(prices[,2]),
low = as.numeric(prices[,3]),
close = as.numeric(prices[,4]))
# Blank plot
p <- plot_ly()
# Add high / low as a line segment
# Add open close as a separate segment
for(i in 1:nrow(prices)){
p <- add_trace(p, data = prices[i,], x = c(time, time), y = c(high, low), mode = "lines", evaluate = T,
showlegend = F,
marker = list(color = "grey"),
line = list(width = 1))
p <- add_trace(p, data = prices[i,], x = c(time, time), y = c(open, close), mode = "lines", evaluate = T,
showlegend = F,
marker = list(color = "#ff5050"),
line = list(width = 5))
}
p
UPDATE:
with the release of plotly 4.0 doing this is a lot easier:
library(plotly)
library(quantmod)
prices <- getSymbols("MSFT", auto.assign = F)
prices <- prices[index(prices) >= "2016-01-01"]
# Make dataframe
prices <- data.frame(time = index(prices),
open = as.numeric(prices[,1]),
high = as.numeric(prices[,2]),
low = as.numeric(prices[,3]),
close = as.numeric(prices[,4]))
plot_ly(prices, x = ~time, xend = ~time, showlegend = F) %>%
add_segments(y = ~low, yend = ~high, line = list(color = "gray")) %>%
add_segments(y = ~open, yend = ~close,
color = ~close > open,
colors = c("#00b386","#ff6666"),
line = list(width = 3))
For a more complete example see here: http://moderndata.plot.ly/candlestick-charts-using-plotly-and-quantmod/
You can do this using the quantmod package.
Try the following:
library(quantmod)
getSymbols("MSFT")
candleChart(MSFT,multi.col=TRUE,theme='white')
You can trim the MSFT object to a smaller date range if you don't need all of them.
If you need to do it with ggplot, let me know and I'll write up the code. But typically, I stick with the packages where I can as it's cleaner!
Royr2 answered this, however he has not moved the answer from comments into answers in a few days, so to capture the answer as a marked answer, I am simply migrating his comment into answers. If he posts his answer, I will gladly mark his answer as the appropriate answer.
"
I wrote something for the folks at plotly here -> http://moderndata.plot.ly/candlestick-charts-using-plotly-and-quantmod/ Uses plot_ly() instead of ggplotly(). Goes without saying that the function is inspired by charts in the quantmod package :) Hopefully helps... –
"
royr2 Apr 25 at 5:02
Related
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
I'm trying to draw some kind of trend line using highs and lows from cryptocurrencies (CC) prices. First libraries I'm using:
library(tidyverse)
library(reshape2)
library(lubridate)
library(TTR)
library(binancer)
library(plotly)
Since I choose among many CC, I'm using next scheme to achieve some kind of automation. For this example, I use Bitcoin (BTC). The following code will retrieve data for Bitcoin for 4 hours timeframe. I set "horas" to 900 in order to get 225 observations:
nombre <- "BTC"
tiempo <- "4h"
horas <- 900
data <- binance_klines(paste0(nombre,"USDT"), interval = paste0(tiempo),
start_time=Sys.time()-hours(paste0(as.numeric(horas))), end_time=Sys.time())%>%
select(open_time, open, high, low, close, volume, trades)%>%
rename(time=1)
Next I get lows and highs to use this data for drawing the lines I want. As you can see, I choose exactly two points for either highs and lows:
lows <- arrange(data, low)%>%
slice(c(which.min(low), which.max(low)))%>%
arrange(time)
highs <- arrange(data, high)%>%
slice(c(which.max(high), which.min(high)))%>%
arrange(time)
And I also add some simple moving averages (SMA). My sma database is the source for my plot:
data%>%
mutate(SMA_5= SMA(close, 5), SMA_10= SMA(close,10), SMA_20= SMA(close,20)) -> sma
I'm trying to use add_segments to draw the line I want for lows (if this works I'll use same code for highs) but I got some error:
sma %>% plot_ly(x = ~time, type="candlestick",
open = ~open, close = ~close,
high = ~high, low = ~low) %>%
add_lines(x = ~time, y= ~SMA_5, line = list(color = "gold", width = 2), inherit = F,
name = "SMA 5", showlegend=T)%>%
add_lines(x = ~time, y= ~SMA_10, line = list(color = "deeppink", width = 2), inherit = F,
name = "SMA 10", showlegend=T)%>%
add_lines(x = ~time, y= ~SMA_20, line = list(color = "purple", width = 2), inherit = F,
name = "SMA 20", showlegend=T)%>%
add_segments(
x = ~lows[1,1], xend = ~lows[2,1],
y = ~lows[1,4], yend = ~lows[2,4], color="black")%>%
plotly::layout(title = paste0(nombre, " Simple Moving Average, ", tiempo),
xaxis= list(title="Time", rangeslider = list(visible = F)), yaxis = list(title = "Price"),
sliders=list(visible=F)) -> sma_plot
sma_plot
Error in `*tmp*`[[jj]] : subscript out of bounds
Any idea on what I'm doing wrong? Any feedback will be highly appreciated.
If you are trying to draw a line between the two coordinates, just use the same pattern you used with the other lines.
add_lines(inherit = F, data = lows, x = ~time, y = ~low,
name = "Lows, line = list(color = "black"))
Hello I am new to plotly in R.
My data is time series with a 95 % credible interval around each point. This credible interval is not symmetric.
The packages I have loaded
library(ggplot2)
library(stringr)
library(dplyr)
library(plotly)
I would like to replicate this ggplot with plotly
ggplot(summarydata, mapping = aes(x = as.Date(Date), y = c.50.))+
geom_errorbar(aes(ymin = c.2.5., ymax = c.97.5.), color ="grey", alpha = .90)+
geom_point()+
scale_x_date(date_labels = "%m-%Y")
My attempts to replicate this in plotly have not succeed
summarydata %>%
plot_ly() %>%
add_markers(x = ~as.Date(Date), y = ~c.50.,
error_y = ~list(symmetric = FALSE,
arrayminus = c.2.5.,
array = c.97.5.,
color = '#000000'))
As you can see the plots error bars are wildly different. I am not sure why this is the case.
The closest I've gotten to replicated my ggplot is with the following
summarydata %>%
plot_ly() %>%
add_markers(x = ~as.Date(Date), y = ~c.50.) %>%
add_markers(x= ~as.Date(Date), y = ~c.97.5., symbol = I("line-ew"), size = 1.5, color = I('rgba(128,128,128, .5)')) %>%
add_markers(x= ~as.Date(Date), y = ~c.2.5., symbol = I("line-ew"), size = 1.5, color = I('rgba(128,128,128, .5)'))
This adds the ticks for the bars as their own marker but when mousing over the plot it is a bit busy to look at. Eventually I am developing a shiny app that will allow users to click on the points and examine them further with supporting graphs. This further business is not ideal
Here is a sample of what my vectors look like that I am working with
summarydata$c.50.[1:10]
[1] 0.6745592 0.6517352 0.6289426 0.7397868 0.7482902 0.6996212 0.6609487 NA NA NA
summarydata$Date[1:10]
[1] "2021-07-07" "2021-07-10" "2021-07-21" "2021-07-23" "2021-07-24" "2021-07-27" "2021-07-28" "2020-04-12" "2020-04-16" "2020-04-18"
summarydata$c.97.5.[1:10]
[1] 0.6879280 0.7240666 0.6506357 0.7425815 0.7500839 0.7026279 0.7130590 NA NA NA
summarydata$c.2.5.[1:10]
[1] 0.6606896 0.6062380 0.6065747 0.7367133 0.7463247 0.6953307 0.5981074 NA NA NA
I figured it out. First off error_y needs the change value and not the value itself
add_markers(x = ~as.Date(Date), y = ~c.50.,
error_y = ~list(symmetric = FALSE,
arrayminus = c.50. - c.2.5., #The change value
array = c.97.5. - c.50.,
color = '#000000')
My second problem is that error_y does not like missing values in their array. x and y have missing and plotly can handle that but for error_y it cannot (I think)
So the complete plot the mimics the ggplot.
summarydata %>%
filter_all(all_vars(!is.na(.))) %>% #error y does not like missing values.
plot_ly() %>%
add_markers(x = ~as.Date(Date), y = ~c.50.,
error_y = ~list(symmetric = FALSE,
arrayminus = c.50. - c.2.5.,
array = c.97.5. - c.50.,
color = '#000000'))
I have spent time researching with no direction on how to create an orbit chart
I would ideally like to be able to create interactive versions (such as Plotly) but a ggplot2 would suffice as well.
Any suggestions are much appreciated!
For a weekly vis contest some time ago, I created some charts like this. I think the commonly accepted term now is "connected scatterplot".
Here is the skeleton plotly code I used.
plot_ly(
df,
x = x_var,
y = y_var,
group = group_var,
mode = "markers") %>%
add_trace(
x = x_var,
y = y_var,
xaxis = list(title = ""),
yaxis = list(title = ""),
group = group_var,
line = list(shape = "spline"),
showlegend = FALSE,
hoverinfo = "none")
You can look at the github repo for my submission which includes the code for both ggplot and plotly to produce connected scatterplots.
Using ggplot2:
geom_path() connects the observations in the order in which they appear in the data. geom_line() connects them in order of the variable on the x axis.
Taken from the ggplot manual page: http://docs.ggplot2.org/current/geom_path.html
You may also try out geom_curve and geom_segment if you want more control.
Thanks to #Bishop, I was able to formulate something really close to my ideal orbit chat. I included some chart annotations, for the start and end date and a label for which direction is the optimal solution.
max_date <- final_data_grp[which.max(final_data_grp$week_num), ]
min_date <- final_data_grp[which.min(final_data_grp$week_num), ]
end <- list(
x = max_date$AreaWOH,
y = max_date$SLevel,
text = paste('End', max_date$MondayDate),
xref = "x",
yref = "y"
)
start <- list(
x = min_date$AreaWOH,
y = min_date$SLevel,
text = paste('Start', min_date$MondayDate),
xref = "x",
yref = "y"
)
best_label = list(
x = min(final_data_grp$AreaWOH),
y = max(final_data_grp$SLevel),
text = 'Best Scenario',
showarrow = FALSE,
bordercolor='#c7c7c7',
borderwidth=2,
borderpad=4,
bgcolor='#ff7f0e',
opacity=.7
)
plot_ly(
final_data_grp,
x = AreaWOH,
y = SLevel,
group = MondayDate,
showlegend = FALSE,
marker = list(size = 8,
color = 'black',
opacity = .6)) %>%
add_trace(
x = AreaWOH,
y = SLevel,
line = list(shape = "spline"),
hoverinfo = "none",
showlegend = FALSE) %>%
layout(annotations = list(start, end, best_label))
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...