shen_qing = "#212A54" # 深青色
qian_qing = "#234C73" # 浅青色
cui_qing = "#263E47" # 翠青色
dan_qing = "#F2F8FF" # 淡青色
hutao_hong = "#793328" # 胡桃红
dan_feng = "#FFF8F0" # 淡粉色
tao_you = "#C0BAB6" # 陶釉色
library(plotly)
library(ggplot2)1 plotly package
- This section also includes Chapter 2 - Overview in Book: Interactive web-based data visualization with R, plotly, and shiny, which has more details about
plotlypackage.
1.1 Set UP
1.2 IVRPS Chapter 2: Basic Information
plotly R package is powered by the Javascript library plotly.js. A plotly object is initialized with a plot_ly() function.
head(diamonds)# A tibble: 6 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
4 0.29 Premium I VS2 62.4 58 334 4.2 4.23 2.63
5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
plot_ly()tries to find a sensible geometric representation of that information forNote that column name is formatted with
~Nameinplot_ly(), which is different fromggplot2packageNameorvars(Name).
subplot(
plot_ly(diamonds, x=~cut),
plot_ly(diamonds, x=~cut, y=~clarity, colors="Accent"),
plot_ly(diamonds, x=~cut, color=~clarity, colors="Accent"),
nrows = 2)Plot 1/2/3
- To specify the color directly, use
I()function to declar the color value as “asis”.
plot_ly(diamonds, x=~cut,
color=I("tomato"),
stroke=I("royalblue"),
span = I(3)) |>
layout(title = "Histogram with I() function")1.2.1 Translate ggplot2 to plotly
In Figure 1, ggplotly() can translate a ggplot2 object into a plotly object.
p <- ggplot(diamonds, aes(x=log(carat), y=log(price))) +
geom_hex(bins = 100)
ggplotly(p)1.2.2 add_ as layers and |> as connection
Plotly implements geoms in a similar fashion as ggplot2, functions that start in add_ add a layer to the plot (e.g.: add_lines, add_bars), making it easy to combine series into a single chart, as in Figure 2.
plot_ly(mtcars, x=~disp) |>
add_markers(y=~mpg, text = rownames(mtcars)) |>
add_lines(y=~fitted(loess(mpg ~ disp)))1.2.3 Data in plotly.js
Use
plotly_json()to see the JSON representation of the plotly object.Use
jasonliteto quickly check jason elements. Check out the package information.
library(jsonlite)
library(tidyverse)
p <- plot_ly(diamonds, x = ~cut, color = ~clarity, colors = "Accent")
p_jason <- plotly_json(p, FALSE, pretty = TRUE) |>
fromJSON()
colnames(p_jason$data) [1] "x" "type" "name" "marker" "textfont" "error_y"
[7] "error_x" "xaxis" "yaxis" "frame"
1.2.4 Work directly with plotly.js
add_trace(type = "scatter", mode = "xxx") function allows you to work directly with plotly.js. This function is a low-level interface to plotly.js, compared to other functions like add_markers.
set.seed(99)
plot_ly() |>
add_trace(
type = "scatter",
mode = "markers+lines+text",
x = 4:6,
y = 4:6,
text = replicate(3, praise::praise("You are ${adjective}! 🙌")),
textposition = "right",
hoverinfo = "text",
textfont = list(family = "MiSans", size = 16)
) |>
layout(xaxis = list(range = c(3, 8)))1.3 IVRPS Chapter 3: Scattered Trace
The trace is general layer in plot.js, which can be specified with a type. The trace layer with type scatter is for drawing geometries like points, lines, text, and polygons.
1.3.1 add_lines and add_paths
add_linesensures lines are drawn according to the ordering of x, which is desirable for a time series plotting. The figure below starts with the lowest value of x —1967-07-01|12.6.add_pathsdraws lines in the order of the data frame (row ordering). As shown in figure below, points starts with the point in the first row—2005-07-01|2.2— then2005-08-01|2.7.If x is sorted from lowest to highest,
add_pathswith be equivalent toadd_lines.
data
library(kableExtra)
data(economics, package = "ggplot2")
economics |>
select(date, psavert) |>
arrange(psavert) |>
head(5) |>
kable()| date | psavert |
|---|---|
| 2005-07-01 | 2.2 |
| 2005-08-01 | 2.7 |
| 2005-09-01 | 2.7 |
| 2005-06-01 | 2.9 |
| 2005-04-01 | 3.1 |
add_paths
p <- economics |>
arrange(psavert) |>
plot_ly(x=~date, y=~psavert)
add_paths(p)add_lines
add_lines(p)add_paths with sorted x values
economics |>
arrange(date) |>
plot_ly(x=~date, y=~psavert, color = I("tomato")) |>
add_paths()1.3.2 Attributes: Group data into sub-gemometry
- Some attributes include color, alpha, symbol, stroke, span, size, linetype.
library(lubridate)
econ <- economics |>
mutate(yr = year(date), mnth = month(date))
plot_ly(econ, x=~mnth, y=~uempmed) |>
add_lines(color=~ordered(yr), colors="Accent")Scatter traces can be specified with a mode of markers (add_markers with a numeric x and y axis). This results in scatterplot.
- Use
alphato adjust the transparancy of scatter points. It can combat with overplotting (points with exactly same x and y values). A location with more points shows less transparent.
subplot(
plot_ly(mpg, x=~cty, y=~hwy, name = "default"),
plot_ly(mpg, x=~cty, y=~hwy) |>
add_markers(alpha = .2, name = "alpha")
)- Use
colorandcolorbar()to produce color trace and color schema. The default colorscale isviridis.
subplot(
plot_ly(mpg, x=~cty, y=~hwy) |>
add_markers(alpha = .2, color=~cyl, showlegend = FALSE) |>
colorbar(title = "Viridis"),
plot_ly(mpg, x=~cty, y=~hwy) |>
add_markers(alpha = .2, color=~factor(cyl), showlegend = FALSE)
)Use
colors=argument to alter the default color scale. (similar toggplot2::scale_color_brewer()). It can be one of the following three types:- color palette name (e.g., check out
RColorBrewer::brewer.pal.info) - a munually specified vector of colors
c("#132B43", "#56B1F7") - a color interpolation function like
colorRamp()orscales::colour_ramp(), i.e.,colorRamp(c("red", "white", "blue"))
- color palette name (e.g., check out
rownames(RColorBrewer::brewer.pal.info) [1] "BrBG" "PiYG" "PRGn" "PuOr" "RdBu" "RdGy"
[7] "RdYlBu" "RdYlGn" "Spectral" "Accent" "Dark2" "Paired"
[13] "Pastel1" "Pastel2" "Set1" "Set2" "Set3" "Blues"
[19] "BuGn" "BuPu" "GnBu" "Greens" "Greys" "Oranges"
[25] "OrRd" "PuBu" "PuBuGn" "PuRd" "Purples" "RdPu"
[31] "Reds" "YlGn" "YlGnBu" "YlOrBr" "YlOrRd"
1.3.3 color= and stroke=
The color argument is meant to control the ‘fill-color’ of a geometric object, whereas stroke is meant to control the ‘outline-color’ of a geometric object.
p <- plot_ly(mpg, x=~cty, y=~hwy)
subplot(
p |>
add_markers(alpha = .2, color=~cyl, showlegend = FALSE),
p |>
add_markers(color=I("black"), stroke=~cyl, showlegend = FALSE)
)- Use
symbolargument to map data values to different shape.
- Use
symbolsto specify certain visual values: “circle”, “diamond” etc.
p <- plot_ly(mpg, x=~cty, y=~hwy, alpha = .3)
subplot(
p |> add_markers(symbol =~factor(cyl), color=I("black"),
symbols = 9:12),
p |> add_markers(symbol =~factor(cyl), color=I("black"),
symbols = c("triangle-up", "diamond", "circle"))
)- Use
spanto control width of the stroke (outline).
subplot(
plot_ly(mpg, x=~cty, y=~hwy, alpha=.5) |>
add_markers(symbol=I(18), stroke=I("black"), span=I(1)),
plot_ly(mpg, x=~cty, y=~hwy, alpha=.5) |>
add_markers(symbol=I(18), stroke=I("black"), span=I(3))
)- Use
sizeto control the area of markers.
- Use
sizesto control the min and max values of size in pixles.
p <- plot_ly(mpg, x=~cty, y=~hwy, alpha = .3)
subplot(
p |> add_markers(size=I(30), name="fixed"),
p |> add_markers(size=~cyl, sizes = c(1, 100), name="custom")
)- Use
linetypeto control line types
econ <- economics |>
mutate(yr = year(date), mnth = month(date)) |>
filter(yr %in% 1967:1972)
plot_ly(data = econ, x=~mnth, y=~uempmed, linetype =~factor(yr), size = I(3)) |>
add_lines()1.4 IVRPS Chapter 5: Bars and Histogram
1.4.1 add_bars() and add_histogram()
Use add_bars() and add_histogram() to wrap the bar plot and the histogram plot. The bar plots requires the height information of bars (x and y), while the histogram requires only x variables.
If the count is calculated in R (using count() for categorical data and hist(plot=FALSE) for continous data), add_bars is faster than add_histogram in terms of page load time.
subplot(
plot_ly(data = diamonds, x=~price) |> add_histogram(name="Histogram", color=I(shen_qing)),
plot_ly(data = diamonds, x=~price, y=~carat) |> add_bars(name="Bar", color=I(hutao_hong))
)1.4.2 Multiple subplots: lapply + subplot
In following code, group_split() is similar to base::split().
one_plot function allows to plot a histogram with x-axis as “price”. add_annotations() adds names of subplots on the top.
library(tidyverse)
one_plot <- function(d) {
plot_ly(d, x = ~price) %>%
add_annotations(
~unique(clarity), x = 0.5, y = 1,
xref = "paper", yref = "paper", showarrow = FALSE
)
}
diamonds |>
group_split(clarity) |>
lapply(one_plot) |>
subplot(nrows = 2, shareX = TRUE, titleX = FALSE) |>
hide_legend()1.4.3 layout(barmode = "stack"): stacked barplot
subplot(
plot_ly(diamonds, x=~cut, color=~clarity) |>
add_histogram() |>
layout(barmode="stack") |>
hide_guides(),
diamonds |>
group_by(cut, clarity) |>
count() |>
group_by(cut) |>
mutate(prop = n / sum(n)) |>
plot_ly(x=~cut, color=~clarity, y=~prop) |>
add_bars() |>
layout(barmode="stack")
)1.5 IVRPS Chapter 8: 3D Charts
1.5.1 Add z attribute to create 3D
By default, with z-axis added, plot_ly will use the scatter plot. Use add_markers() to specify 3D scatter plot.
p_3d <- plot_ly(data = mpg, x=~cty, y=~hwy, z=~cyl, color=~cyl) |>
add_markers(alpha = .4, stroke = I("black"))
p_3d1.5.2 layout(scene): set up axis for 3D chart
Below plot set up titles for x/y/z-axis inside scene. Use R list object to specify multiple attributes in layout.
p_3d |>
layout(
scene = list(
xaxis = list(title = "MPG city"),
yaxis = list(title = "MPG highway"),
zaxis = list(title = "Number of cylinders")
)
)1.5.3 add_surface(): 3d surface
For 3D surface, z-axis is a continuous surface (a matrix) with the same ordering with x and y. plot.js will automatically interpolate the gaps among points to create the surface.
For example, datasets::volcano is a matrix with 87 rows and 61 columns, with rows corresponding to grid lines running east to west and columns to south to north. So the height of volcano will be the z-axis.
x <- seq_len(nrow(volcano)) + 100
y <- seq_len(ncol(volcano)) + 500
plot_ly() |> add_surface(x=~x, y=~y, z=~volcano)1.7 IVRPS Chapter 11: Exporting static images
1.8 IVRPS Chapter 13: Arragement
1.8.1 subplot: set up the layout of multiple plots
subplot accepts arbitary plots or a list of plots generated by lapply.
library(plotly)
p1 <- plot_ly(economics, x = ~date, y = ~unemploy) |>
add_lines(name = "unemploy")
p2 <- plot_ly(economics, x = ~date, y = ~uempmed) |>
add_lines(name = "uempmed")
subplot(p1, p2) # subplot(list(p1, p2))- Use
nrows = length(plots)to arrange plots into 1 columns. - Use
shareX=TRUEargument to make sure all plots share the same x-axis.
vars <- setdiff(names(economics), "date")
plots <- lapply(vars, function(var) {
plot_ly(economics, x = ~date, y = as.formula(paste0("~", var))) %>%
add_lines(name = var)
})
subplot(plots, nrows = length(plots), shareX = TRUE, titleX = FALSE)