library (plotly)
## Loading required package: ggplot2
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(listviewer)
library (ggforce)
library (modelr)
library (GGally)
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
library(naniar)
library (lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(quantmod)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## ################################### WARNING ###################################
## # We noticed you have dplyr installed. The dplyr lag() function breaks how #
## # base R's lag() function is supposed to work, which breaks lag(my_xts). #
## # #
## # Calls to lag(my_xts) that you enter or source() into this session won't #
## # work correctly. #
## # #
## # All package code is unaffected because it is protected by the R namespace #
## # mechanism. #
## # #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## # You can use stats::lag() to make sure you're not using dplyr::lag(), or you #
## # can add conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## ################################### WARNING ###################################
##
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
##
## first, last
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
los graficos son creados con el paquete plotly R funciona con la biblioteca de JavaScript plotly.js La plot_ly()función proporciona una interfaz ‘directa’ para plotly.js con algunas abstracciones adicionales para ayudar a reducir la escritura. Estas abstracciones, inspiradas en Grammar of Graphics y ggplot2 , hacen que sea mucho más rápido iterar de un gráfico a otro, lo que facilita descubrir características interesantes en los datos
data("diamonds", package = "ggplot2")
En la seccion 2 se puedo evidenciar la introduccion de argumentos de “asignación estética” (exclusivos del paquete R) que facilitan la asignación de datos a propiedades visuales (p. ej., color, linetype, etc.). Además de estos argumentos, las agrupaciones dplyr se pueden usar para garantizar que haya al menos una geometría por grupo.
la primer grafica de la siguiente figura demuestra cómo [group_by() ]podría usarse para envolver de manera efectiva la serie temporal de la soguiente figura por año, lo que puede ser útil para visualizar la estacionalidad anual
data(economics, package = "ggplot2")
# sort economics by psavert, just to
# show difference between paths and lines
p <- economics %>%
arrange(psavert) %>%
plot_ly(x = ~date, y = ~psavert)
add_paths(p)
add_lines(p)
Estos gráficos no solo difieren en apariencia visual, también difieren en capacidades interactivas, rendimiento computacional e implementación subyacente. Esto se debe a que el enfoque de agrupación de la figura superior de la siguiente grafica usa solo un seguimiento de plotly.js más eficaz pero menos interactivo, mientras que el color enfoque la figura inferioir de la siguiente grafica genera un seguimiento por línea/año, lo que lo hace mas interactivo.
Estas características hacen que sea más fácil comenzar a usar plotly.js, pero vale la pena aprender a usar plotly.js directamente. No encontrará atributos de plotly.js enumerados como argumentos explícitos en ninguna función de plotly (excepto el typeatributo especial)
library(lubridate)
econ <- economics %>%
mutate(yr = year(date), mnth = month(date))
# One trace (more performant, but less interactive)
econ %>%
group_by(yr) %>%
plot_ly(x = ~mnth, y = ~uempmed) %>%
add_lines(text = ~yr)
# Multiple traces (less performant, but more interactive)
plot_ly(econ, x = ~mnth, y = ~uempmed) %>%
add_lines(color = ~ordered(yr))
Las capas basadas en dispersión en este capítulo corrigen el typeatributo plotly.js “scatter”así como mode (por ejemplo, add_markers()usos mode=‘markers’, etc.), pero también puede usar el nivel inferior add_trace()para trabajar más directamente con plotly.js. Por ejemplo, la figura 3.3 muestra cómo representar marcadores, líneas y texto en el mismo trazo de dispersión.
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 = "Roboto Condensed", size = 16)
) %>%
layout(xaxis = list(range = c(3, 8)))
para buscar y aprender sobre los atributos en linea podemos encontrar muchas referencias, pero el autor recomienda usar la [schema()función556] en su lugar por varias razones:
schema()
Esta sección detalla las trazas de dispersión con un modede “markers”(es decir, add_markers()). Para simplificar, muchos de los ejemplos aquí se usan add_markers()con un eje numérico x e y, lo que da como resultado un diagrama de dispersión.
los diagramas de dispersión pueden ser útiles para exponer otras características importantes, entre ellas: relaciones casuales, valores atípicos, conglomerados, brechas, barreras y relaciones condicionales.
un problema comun en los diagramas de dispersion es la sobregraficacion, dado que hay muchos datos que ocupan la misma posicion, para esto hay un forma de corregirlo, a traves de la combinacion alfa como se muestra en la siguiente figura, cuando se tienen decenas de punto se puede usar una funcion llamada toWebGL()para renderizar gráficos
subplot(
plot_ly(mpg, x = ~cty, y = ~hwy, name = "default"),
plot_ly(mpg, x = ~cty, y = ~hwy) %>%
add_markers(alpha = 0.2, name = "alpha")
)
## No trace type specified:
## Based on info supplied, a 'scatter' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
La colorbar()función se puede utilizar para personalizar la apariencia de esta guía generada automáticamente. La escala de colores predeterminada es viridis, una escala de colores perceptualmente uniforme (incluso cuando se convierte a blanco y negro) y perceptible incluso para aquellos con formas comunes de daltonismo ( Berkeley Institute for Data Science 2016 ) . Viridis es también la escala de colores predeterminada para los factores ordenados.
p <- plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.5)
subplot(
add_markers (p, color = ~cyl, showlegend = FALSE) %>%
colorbar(title = "Viridis"),
add_markers(p, color = ~factor(cyl)))
Existen numerosas formas de alterar la escala de color predeterminada a través del colorsargumento. Este argumento exceptúa uno de los siguientes: (1) un nombre de paleta de cervecero de color (consulte los nombres de fila de RColorBrewer::brewer.pal.infopara obtener nombres válidos), (2) un vector de colores para interpolar, o (3) una función de interpolación de color como colorRamp()o scales::colour_ramp()
col1 <- c("#132B43", "#56B1F7")
col2 <- viridisLite::inferno(10)
col3 <- colorRamp(c("red", "white", "blue"))
subplot(
add_markers(p, color = ~cyl, colors = col1) %>%
colorbar(title = "ggplot2 default"),
add_markers(p, color = ~cyl, colors = col2) %>%
colorbar(title = "Inferno"),
add_markers(p, color = ~cyl, colors = col3) %>%
colorbar(title = "colorRamp")
) %>% hide_legend()
Como se presenta en la figura anterioir, los códigos de color se pueden especificar manualmente (es decir, evitar asignar valores de datos a un rango visual) usando la I()función. La siguiente figura proporciona un ejemplo simple usando add_markers().Cualquier color entendido por la col2rgb()función del paquete grDevices se puede utilizar de esta manera
col1 <- "Accent"
col2 <- colorRamp(c("red", "blue"))
col3 <- c(`4` = "red", `5` = "black", `6` = "blue", `8` = "green")
subplot(
add_markers(p, color = ~factor(cyl), colors = col1),
add_markers(p, color = ~factor(cyl), colors = col2),
add_markers(p, color = ~factor(cyl), colors = col3)
) %>% hide_legend()
En el caso de add_markers(), eso significa colorque se asigna al atributo plotly.js marker.colory strokese asigna a marker.line.color. No todos, pero muchos, los símbolos de marcador tienen una noción de trazo.
add_markers(p, color = I("black"))
El symbolargumento se puede usar para asignar valores de datos al (marker.symbolatributo plotly.js. ) Utiliza la misma semántica que ya hemos visto para color:
en la siguiente figura se observa que la grafica izquierda usa un mapeo numérico y la grafica de la derecha derecho usa un mapeo discreto. Como resultado, el panel izquierdo está vinculado a la primera entrada de leyenda, mientras que el panel derecho está vinculado a las tres entradas de leyenda inferiores.
p <- plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.3)
subplot(
add_markers(p, symbol = ~cyl, name = "A single trace"),
add_markers(p, symbol = ~factor(cyl), color = I("black"))
)
Hay dos formas de especificar el rango visual de symbols: (1) códigos numéricos (interpretados como pchcódigos) o (2) una cadena de caracteres que especifica un marker.symbolvalor válido. la siguiente figura usa códigos pch (panel izquierdo) así como su marker.symbolnombre correspondiente (panel derecho) para especificar el rango visual.
subplot(
add_markers(p, symbol = ~cyl, symbols = c(17, 18, 19)),
add_markers(
p, color = I("black"),
symbol = ~factor(cyl),
symbols = c("triangle-up", "diamond", "circle")
)
)
Estos symbols(es decir, el rango visual) también se pueden suministrar directamente a symboltravés de I()
plot_ly(mpg, x = ~cty, y = ~hwy) %>%
add_markers(symbol = I(18), alpha = 0.5)
El strokeargumento sigue la misma semántica colorcuando symbolse trata de asignaciones de variables y especificación de rangos visuales. Por lo general, no desea asignar valores de datos a stroke, solo desea especificar un color de contorno fijo
En la siguiente figura se modifica para solo agregarun contorno negro. De forma predeterminada, el spanancho del trazo es cero; es probable que desee establecer el ancho en alrededor de un píxel.
plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.5) %>%
add_markers(symbol = I(18), stroke = I("black"), span = I(1))
Para diagramas de dispersión, el sizeargumento controla el área de los marcadores (a menos que se especifique lo contrario a través de sizemode ) y debe ser una variable numérica. El sizesargumento controla el tamaño mínimo y máximo de los círculos, en píxeles:
p <- plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.3)
subplot(
add_markers(p, size = ~cyl, name = "default"),
add_markers(p, size = ~cyl, sizes = c(1, 500), name = "custom")
)
## Warning: `line.width` does not currently support multiple values.
## Warning: `line.width` does not currently support multiple values.
Similar a otros argumentos, I()se puede usar para especificar el tamaño directamente. En el caso de los marcadores, sizecontrola el marker.sizeatributo plotly.js.
plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.3, size = I(30))
## No trace type specified:
## Based on info supplied, a 'scatter' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
los diagramas de puntos son preferibles a los gráficos circulares, ya que comparar posiciones a lo largo de una escala común es mucho más fácil que comparar ángulos o áreas, Además, los diagramas de puntos pueden ser preferibles a los gráficos de barras, especialmente cuando se comparan valores dentro de un rango estrecho lejos de 0. asi que, cuando se presentan estimaciones puntuales y la incertidumbre asociada con esas estimaciones, los gráficos de barras tienden a exagerar la diferencia en las estimaciones puntuales y pierden el enfoque en la incertidumbre.
Una aplicación popular para diagramas de puntos (con barras de error) es el llamado “gráfico de coeficientes” para visualizar las estimaciones puntuales de los coeficientes y su error estándar. La coefplot()función en el paquete coefplot y la ggcoef()función en GGally producen gráficos de coeficientes para muchos tipos de objetos modelo en R usando ggplot2 , que podemos traducir a plotly a través de ggplotly()
m <- lm(
Sepal.Length ~ Sepal.Width * Petal.Length * Petal.Width,
data = iris)
broom::tidy(m) %>%
mutate(term = forcats::fct_reorder(term, estimate)) %>%
plot_ly(x = ~estimate, y = ~term) %>%
add_markers(
error_x = ~list(value = std.error),
color = I("black"),
hoverinfo = "x"
)
En este capítulo, aprenderemos sobre linetype/ linetype, una estética que se aplica a líneas y polígonos. También discutiremos algunos otros tipos de gráficos importantes que se pueden implementar con add_paths(), add_lines()y add_segments().
Aquí usamos el paquete dplyr para encontrar las 5 ciudades principales en términos de ventas mensuales promedio ( top5), luego filtramos de manera efectiva los datos originales para que contengan solo estas ciudades a través de semi_join()
una vez que tenemos los datos filtrados, mapear la ciudad hacia coloro linetypees trivial. La paleta de colores se puede modificar a través del colorsargumento y sigue las mismas reglas que los diagramas de dispersión . La paleta de tipo de línea se puede modificar a través del linetypesargumento y acepta ltylos valores de R o los valores de guiones de plotly.js .
top5 <- txhousing %>%
group_by(city) %>%
summarise(m = mean(sales, na.rm = TRUE)) %>%
arrange(desc(m)) %>%
top_n(5)
## Selecting by m
tx5 <- semi_join(txhousing, top5, by = "city")
plot_ly(tx5, x = ~date, y = ~median) %>%
add_lines(linetype = ~city)
Si desea controlar exactamente qué tipo de línea se usa para codificar un valor de datos en particular, puede proporcionar un vector de caracteres con nombre.
ltys <- c(
Austin = "dashdot",
`Collin County` = "longdash",
Dallas = "dash",
Houston = "solid",
`San Antonio` = "dot")
plot_ly(tx5, x = ~date, y = ~median) %>%
add_lines(linetype = ~city, linetypes = ltys)
La add_segments()función proporciona esencialmente una forma de conectar dos puntos [( x, y) a ( xend, yend)] con una línea. Los segmentos forman los bloques de construcción para numerosos tipos de gráficos útiles, incluidos gráficos de pendiente, gráficos con mancuernas, gráficos de velas y más.
Los segmentos también pueden proporcionar una alternativa útil a add_bars()(cubierto en el Capítulo 5 ), especialmente para animaciones.
#data (gdp, package = "newggslopegraph")
#plot_ly(gpd) %>%
# add_segments(
# x = 1, xend = 2,
#y = ~year1970, yend = ~year1969,
# color = I("gray90")
# )
#add_annotations(
# x = 1, y = ~year1970,
# text = "rigth", showarrow = FALSE
#) %>%
#add_annotations(
# x = 2, y = ~year1979,
#text = ~paste(year1979, " ", country)
#xanchor = "left", showarrow = FALSE
#) %>%
#layout (
# title = "Current Receipts of Government as a Percentage of Gop",
#showlegend = FALSE,
# xaxis = list(
#range = c(0, 3),
# Ticktext = c(1, 2),
#zeroline = FALSE
#) ,
#yaxis = list(
#title = "",
#showgrid = FALSE,
#Showticks = FALSE,
#Shouwticklabels = FALSE
# )
#) %>%
# config(edits = list (annotationposition = TRUE))
El gráfico de pendiente, es una excelente manera de comparar el cambio en una medición entre numerosos grupos. Este cambio podría ser a lo largo de un eje discreto o continuo. Para un eje continuo, el gráfico de pendientes podría considerarse como una descomposición de un gráfico lineal en múltiples segmentos.
mpg %>%
group_by(model) %>%
summarise(c = mean(cty), h = mean(hwy)) %>%
mutate(model = forcats::fct_reorder(model, c)) %>%
plot_ly() %>%
add_segments(
x = ~c, y = ~model,
xend = ~h, yend = ~model,
color = I("gray"), showlegend = FALSE
) %>%
add_markers(
x = ~c, y = ~model,
color = I("blue"),
name = "mpg city"
) %>%
add_markers(
x = ~h, y = ~model,
color = I("red"),
name = "mpg highway"
) %>%
layout(xaxis = list(title = "Miles per gallon"))
Los llamados gráficos con mancuernas son similares en concepto a los gráficos de pendiente, pero no tan generales. Por lo general, se utilizan para comparar dos clases diferentes de valores numéricos en numerosos grupos.
utiliza el método de pesas para mostrar el promedio de millas por galón en ciudad y carretera para diferentes modelos de automóviles.
msft <- getSymbols("MSFT", auto.assign = F)
dat <- as.data.frame(msft)
dat$date <- index(msft)
dat <- subset(dat, date >= "2016-01-01")
names(dat) <- sub("^MSFT\\.", "", names(dat))
plot_ly(dat, x = ~date, xend = ~date, color = ~Close > Open,
colors = c("red", "forestgreen"), hoverinfo = "none") %>%
add_segments(y = ~Low, yend = ~High, size = I(1)) %>%
add_segments(y = ~Open, yend = ~Close, size = I(3)) %>%
layout(showlegend = FALSE, yaxis = list(title = "Price")) %>%
rangeslider()
La siguiente figura usa el paquete quantmod para obtener datos de precios de acciones de Microsoft y traza dos segmentos para cada día uno para codificar los valores de apertura/cierre y otro para codificar el máximo/mínimo diario.
Esta implementación utiliza [ add_segments() ]para implementar el gráfico de velas, pero las versiones más recientes de plotly.js contienen tipos de seguimiento de velas y ohlc , los cuales son útiles para visualizar datos financieros.
kerns <- c("gaussian", "epanechnikov", "rectangular",
"triangular", "biweight", "cosine", "optcosine")
p <- plot_ly()
for (k in kerns) {
d <- density(economics$pce, kernel = k, na.rm = TRUE)
p <- add_lines(p, x = d$x, y = d$y, name = k)
}
p
aprovechamos una serie de algoritmos en R para calcular el número “óptimo” de contenedores para un histograma, vía hist()y enrutar esos resultados a add_bars()
Podemos aprovechar la density()función para calcular las estimaciones de densidad del kernel de manera similar y enrutar los resultados a add_lines(), como se hace en la siguiente figura.
iris$obs <- seq_len(nrow(iris))
iris_pcp <- function(transform = identity) {
iris[] <- purrr::map_if(iris, is.numeric, transform)
tidyr::gather(iris, variable, value, -Species, -obs) %>%
group_by(obs) %>%
plot_ly(x = ~variable, y = ~value, color = ~Species) %>%
add_lines(alpha = 0.3)
}
subplot(
iris_pcp(),
iris_pcp(scale),
iris_pcp(scales::rescale),
nrows = 3, shareX = TRUE
) %>% hide_legend()
## Warning: attributes are not identical across measure variables; they will be
## dropped
La add_polygons()función es esencialmente equivalente a add_paths()tener el atributo de relleno establecido en “a sí mismo”. Los polígonos forman la base para otras capas basadas en dispersión de nivel superior (por ejemplo, add_ribbons()y add_sf()) que no tienen un tipo de seguimiento plotly.js dedicado
Los polígonos se pueden usar para dibujar muchas cosas, pero quizás la aplicación más familiar que podría querer usar add_polygons()es para dibujar objetos geoespaciales. Si usa add_polygons()para dibujar un mapa, asegúrese de corregir la relación de aspecto (p. ej., xaxis.scaleanchor) y también considere usar plotly_empty()over plot_ly()para ocultar las etiquetas de los ejes
base <- map_data("world", "canada") %>%
group_by(group) %>%
plotly_empty(x = ~long, y = ~lat, alpha = 0.2) %>%
layout(showlegend = FALSE, xaxis = list(scaleanchor = "y"))
base %>%
add_polygons(hoverinfo = "none", color = I("black")) %>%
add_markers(text = ~paste(name, "<br />", pop), hoverinfo = "text",
color = I("red"), data = maps::canada.cities)
Como señala la discusión en torno a la Figura 4.10 , las capas de polígonos basadas en dispersión (es decir, add_polygons(), add_ribbons(), etc.) representan todos los polígonos usando un trazado de plotly.js de manera predeterminada. Este enfoque es computacionalmente eficiente, pero no siempre es deseable (p. ej., no puede tener varios rellenos por seguimiento, la interactividad es relativamente limitada). Para evitar las limitaciones, considere usar split(o colorcon una variable discreta) para dividir los datos del polígono en varias trazas.
add_polygons(base, split = ~subregion, hoveron = "fills")
Las cintas son útiles para mostrar los límites de incertidumbre en función de x. La add_ribbons()función crea cintas y requiere los argumentos: x, yminy ymax. La augment()función del paquete de escoba agrega componentes del modelo de nivel de observación (por ejemplo, valores ajustados almacenados como una nueva columna .fitted
#m <- lm(mpg ~ wt, data = mtcars)
#broom::augment(m) %>%
# plot_ly(x = ~wt, showlegend = FALSE) %>%
#add_markers(y = ~mpg, color = I("black")) %>%
#add_ribbons(ymin = ~.fitted - 1.96 * .se.fit,
# ymax = ~.fitted + 1.96 * .se.fit,
# color = I("gray80")) %>%
#add_lines(y = ~.fitted, color = I("steelblue"))