Las funciones “add_bars()” y “add_histogram()” envuelven los tipos de trazos bar’ e histogram “plotly.js”. La principal diferencia entre ellos es que los trazos de bar’ requieren alturas de barra (tanto x como y), mientras que los trazos de histogram requieren solo una variable y plotly.js maneja la agrupación en el navegador. Y quizás de manera confusa, ambas funciones se pueden usar para visualizar la distribución de una variable numérica o discreta. Entonces, esencialmente, la única diferencia entre ellos es dónde ocurre la agrupación.
La Figura 5.1 compara el algoritmo de agrupación predeterminado en plotly.js con algunos algoritmos diferentes disponibles en R mediante la función “hist()”. Aunque plotly.js tiene la capacidad de personalizar contenedores de histograma a través de xbins/ybins, R tiene diversas funciones para estimar el número óptimo de contenedores en un histograma que podemos aprovechar fácilmente”. La función “hist()” por sí sola nos permite hacer referencia a 3 algoritmos famosos por nombre (Sturges, 1926; Freedman y Diaconis, 1981; Scott, 1979), pero también hay paquetes (por ejemplo, el paquete de histogramas) que amplían esta interfaz para incorporar más metodología (Mildenberger et al., 2009). ) a continuación envuelve la función hist() para obtener los resultados de agrupación y asigna esos contenedores a una versión gráfica del histograma usando add_bars().
library(plotly)
## Warning: package 'plotly' was built under R version 4.3.3
## 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
# Crea un histograma usando plot_ly
pl <- plot_ly(diamonds, x = ~price) %>%
add_histogram(name = "plotly.js")
# Define una función para crear histogramas de precios
price_hist <- function(method = "FD") {
h <- hist(diamonds$price, breaks = method, plot = FALSE)
plot_ly(x = h$mids, y = h$counts) %>% add_bars(name = method)
}
# Crea histogramas usando diferentes métodos
p1 <- price_hist()
p2 <- price_hist("Sturges")
p3 <- price_hist("Scott")
# Crea subgráficos
subplot(p1, p2, p3, nrows = 3, shareX = TRUE)
FIGURA 5.1: El algoritmo de agrupamiento predeterminado de plotly.js versus el predeterminado hist() de R.
La figura 5.2 muestra dos formas de crear un gráfico de barras básico. Aunque los resultados visuales son los mismos, vale la pena señalar la diferencia en la implementación. La función add_histogram() envía todos los valores observados al navegador y permite que plotly.js realice la agrupación.
Se necesita más esfuerzo humano para realizar la agrupación en R, pero hacerlo tiene la ventaja de enviar menos datos y requerir menos trabajo de cálculo por parte del navegador web. En este caso, solo tenemos unos 50.000 registros, por lo que no hay mucha diferencia en los tiempos de carga de la página o el tamaño de la página. Sin embargo, con 1 millón de registros, el tiempo de carga de la página se duplica y el tamaño de la página casi se duplica.
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(plotly)
# Crear el primer gráfico de histograma
p1 <- plot_ly(diamonds, x = ~cut) %>%
add_histogram()
# Crear el segundo gráfico de barras
p2 <- diamonds %>%
count(cut) %>%
plot_ly(x = ~cut, y = ~n) %>%
add_bars()
# Crear un subplot y ocultar la leyenda
subplot(p1, p2) %>% hide_legend()
FIGURE 5.2: Number of diamonds by cut.
##5.1 Distribuciones numéricas múltiples A menudo resulta útil ver cómo cambia la distribución numérica con respecto a una variable discreta. Cuando utilice barras para visualizar múltiples distribuciones numéricas, recomiendo trazar cada distribución en su propio eje usando una pequeña visualización de múltiplos, en lugar de intentar superponerlas en un solo eje. El Capítulo 13, y específicamente la Sección 13.1.2.3, analiza los múltiplos pequeños con más detalle, pero la Figura 13.9 demuestra cómo se hace con plot_ly() y subplot(). Observe cómo la función one_plot() define qué mostrar en cada panel, luego se emplea una estrategia dividir-aplicar-recombinar (es decir, dividir(), lapply(), subplot()) para generar la visualización enrejada.
library(dplyr)
library(plotly)
# Definir la función para crear un gráfico
one_plot <- function(d) {
plot_ly(d, x = ~price) %>%
add_annotations(
text = unique(d$clarity), x = 0.5, y = 1, xref = "paper", yref = "paper", showarrow = FALSE
)
}
# Aplicar la función a cada grupo de datos dividido por claridad
diamonds %>%
split(.$clarity) %>%
lapply(one_plot) %>%
subplot(nrows = 2, shareX = TRUE, titleX = FALSE) %>%
hide_legend()
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
## No trace type specified:
## Based on info supplied, a 'histogram' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#histogram
##5.2 Distribuciones discretas múltiples Visualizar múltiples distribuciones discretas es difícil. La sutil complejidad se debe al hecho de que tanto los recuentos como las proporciones son importantes para comprender distribuciones discretas multivariadas. La Figura 5.4 presenta el recuento de diamantes, dividido tanto por talla como por claridad, utilizando un gráfico de barras agrupadas.
library(plotly)
# Crear el histograma con diferentes colores para cada nivel de claridad
plot_ly(diamonds, x = ~cut, color = ~clarity) %>%
add_histogram()
FIGURA 5.4: Gráfico de barras agrupadas de recuentos de diamantes por talla y claridad.
La figura 5.4 es útil para comparar el número de diamantes por claridad, dado un tipo de talla. Por ejemplo, dentro de los diamantes “ideales”, la talla “VS1” es la más popular, la “VS2” es la segunda más popular y la “11” la menos popular. La distribución de la claridad dentro de los diamantes “ideales” parece ser bastante similar a la de otros diamantes, pero es difícil hacer esta comparación utilizando recuentos brutos. La figura 5.5 facilita esta comparación al mostrar la frecuencia relativa de los diamantes por claridad, dada una talla.
library(dplyr)
library(plotly)
# Número de diamantes por corte y claridad (n)
cc <- diamonds %>%
count(cut, clarity)
# Número de diamantes por corte (nn)
cc2 <- cc %>%
left_join(count(cc, cut, wt = n, name = 'nn'))
## Joining with `by = join_by(cut)`
# Calcular la proporción
cc2 <- cc2 %>%
mutate(prop = n / nn)
# Crear el gráfico de barras
plot_ly(cc2, x = ~cut, y = ~prop, color = ~clarity, type = "bar") %>%
layout(barmode = "stack")
FIGURA 5.5: Un gráfico de barras apiladas que muestra la proporción de claridad del diamante dentro del corte.
Este tipo de trama, también conocida como trama espinal, es un caso especial de trama en mosaico. En un gráfico de mosaico, puede escalar tanto el ancho como la altura de las barras según distribuciones discretas. Para gráficos de mosaico, recomiendo usar el paquete ggmosaic (Jeppson et al., 2016), que implementa un geom ggplot2 personalizado diseñado para gráficos de mosaico, que podemos convertir a plotly mediante ggplotly (). La Figura 5.6 muestra un diagrama de mosaico de corte por claridad. Observe cómo los anchos de las barras se escalan proporcionalmente a la frecuencia de corte.
library(ggmosaic)
## Warning: package 'ggmosaic' was built under R version 4.3.3
library(plotly)
# Crear el gráfico de mosaico
p <- ggplot(data = cc) +
geom_mosaic(aes(weight = n, x = product(cut), fill = clarity))
# Convertir el gráfico de ggplot a plotly
ggplotly(p)
## Warning: `unite_()` was deprecated in tidyr 1.2.0.
## ℹ Please use `unite()` instead.
## ℹ The deprecated feature was likely used in the ggmosaic package.
## Please report the issue at <https://github.com/haleyjeppson/ggmosaic>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
FIGURA 5.6: Uso de ggmosaic y ggplotly() para crear visualizaciones interactivas avanzadas de datos categóricos.
Los diagramas de caja codifican el resumen de cinco números de una variable numérica y proporcionan una forma decente de comparar muchas distribuciones numéricas. La tarea visual de comparar múltiples diagramas de caja es relativamente fácil (es decir, comparar la posición a lo largo de una escala común) en comparación con algunas alternativas comunes (por ejemplo, una visualización enrejada de histogramas, como la Figura 5.1), pero el diagrama de caja a veces es inadecuado para capturar distribuciones complejas (por ejemplo, multimodales) (en este caso, un polígono de frecuencia, como el de la Figura 2.9, proporciona una buena alternativa). La función add_boxplot() requiere una variable numérica y garantiza que los diagramas de caja estén orientados correctamente, independientemente de si la variable numérica se coloca en la escala x o y. Como muestra la Figura 6.1, en el eje ortogonal al eje numérico, puede proporcionar una variable discreta (para acondicionamiento) o proporcionar un valor único (para nombrar la categoría del eje).
library(plotly)
# Crear un diagrama de caja con puntos de datos transparentes
p <- plot_ly(diamonds, y = ~price, color = I("black"),
alpha = 0.1, boxpoints = "suspectedoutliers")
# Añadir un diagrama de caja a 'p' con la variable "Overall" en el eje x
pl <- p %>% add_boxplot(x = "Overall")
# Añadir otro diagrama de caja a 'p' con la variable "cut" en el eje x
p2 <- p %>% add_boxplot(x = ~cut)
# Crear los subgráficos
subplot(
pl, p2, shareY = TRUE,
widths = c(0.2, 0.8), margin = 0
) %>% hide_legend()
FIGURA 6.1: Precio general del diamante y precio por talla.
Si desea dividir por más de una variable discreta, puede usar la interacción de esas variables con el eje discreto y colorear por la variable anidada, como lo hace la Figura 6.2 con la claridad y el corte del diamante. Otro enfoque sería utilizar una pantalla enrejada, similar a la Figura 13.9.
library(plotly)
# Crear un diagrama de caja con la variable 'price' en el eje x y la interacción entre 'clarity' y 'cut' en el eje y
plot_ly(diamonds, x = ~price, y = ~interaction(clarity, cut)) %>%
add_boxplot(color = ~clarity) %>%
layout(yaxis = list(title = ""))
FIGURA 6.2: Precios de los diamantes por talla y claridad.
También resulta útil ordenar los diagramas de caja según algo significativo, como el precio medio. La Figura 6.3 presenta la misma información que la Figura 6.2, pero ordena los diagramas de caja por su mediana y deja inmediatamente claro que los diamantes con una talla “SI2” tienen el precio más alto, en promedio.
library(dplyr)
library(plotly)
# Añadir la interacción entre 'clarity' y 'cut' como una nueva variable 'cc'
d <- diamonds %>%
mutate(cc = interaction(clarity, cut))
# Obtener los niveles de interacción ordenados por la mediana del precio
lvls <- d %>%
group_by(cc) %>%
summarise(m = median(price)) %>%
arrange(m) %>%
pull(cc)
# Crear el gráfico de diagrama de caja
plot_ly(d, x = ~price, y = ~factor(cc, levels = lvls)) %>%
add_boxplot(color = ~clarity) %>%
layout(yaxis = list(title = ""))
FIGURA 6.3: Precios de los diamantes por talla y claridad, ordenados por mediana de precios.
Similar a add_histogram(), add_boxplot() envía los datos sin procesar al navegador y permite que plotly.js calcule estadísticas resumidas. Desafortunadamente, plotly.js aún no permite estadísticas precalculadas para diagramas de caja.
##7.1 Agrupación rectangular en plotly.js El paquete plotly proporciona dos funciones para mostrar contenedores rectangulares: add_heatmap() y add_histogram2d(). Para datos numéricos, la función add_heatmap() es un análogo 2D de add_bars() (los bins deben calcularse previamente), y la función add_histogram2d() es un análogo 2D de add_histogram() (los bins se pueden calcular en el navegador). Por lo tanto, recomiendo add_histogram2d() con fines exploratorios, ya que no es necesario pensar en cómo realizar la agrupación. También proporciona un útil atributo zs-mooth¹ para aumentar efectivamente el número de contenedores (actualmente, “best” realiza una interpolación bilineal², un tipo de algoritmo de vecinos más cercanos) y atributos nbinsx³/nbinsy para establecer el número de contenedores en el direcciones x y/o y. La Figura 7.1 compara tres usos diferentes de add_histogram(): (1) el algoritmo de agrupamiento predeterminado de plotly.js, (2) el suavizado predeterminado más, (3) establecer el número de bins en las direcciones x e y. También vale la pena señalar que los contornos rellenos, en lugar de contenedores, se pueden usar en cualquiera de estos casos usando add_histogram2dcontour() en lugar de add_histogram2d().
library(plotly)
# Crear un gráfico scatter plot con el eje x como 'carat' y el eje y como logaritmo de 'price'
p <- plot_ly(diamonds, x = ~carat, y = ~log(price), type = "scatter", mode = "markers")
# Crear subplots con histogramas 2D y configuraciones específicas
subplot(
p %>% add_histogram2d() %>% colorbar(title = "default") %>% layout(xaxis = list(title = "default")),
p %>% add_histogram2d(zsmooth = "best") %>% colorbar(title = "zsmooth") %>% layout(xaxis = list(title = "zsmooth")),
p %>% add_histogram2d(nbinsx = 60, nbinsy = 68) %>% colorbar(title = "nbins") %>% layout(xaxis = list(title = "nbins")),
shareY = TRUE, titleX = TRUE
)
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
## Warning: 'histogram2d' objects don't have these attributes: 'mode'
## Valid attributes include:
## 'autobinx', 'autobiny', 'autocolorscale', 'bingroup', 'coloraxis', 'colorbar', 'colorscale', 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertemplate', 'hovertemplatesrc', 'ids', 'idssrc', 'legendgroup', 'legendgrouptitle', 'legendrank', 'marker', 'meta', 'metasrc', 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', 'showlegend', 'showscale', 'stream', 'textfont', 'texttemplate', 'transforms', 'type', 'uid', 'uirevision', 'visible', 'x', 'xaxis', 'xbingroup', 'xbins', 'xcalendar', 'xgap', 'xhoverformat', 'xsrc', 'y', 'yaxis', 'ybingroup', 'ybins', 'ycalendar', 'ygap', 'yhoverformat', 'ysrc', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmid', 'zmin', 'zsmooth', 'zsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'