Visualización de datos

¿Cómo y qué es?

A través de la visualización de datos podemos mostrar patrones, trends y correlaciones en los datos en un contexto visual.

Ventajas:

  • intuitiva

  • inmediata

  • pegajosa

Desventaja:

  • puede ser engañosa

  • tenemos a lo muchos 3 dimensiones

Hay diferentes librearias que podemos utilizar para realizar nuestra graficas y pueden ser de más alto o bajo nivel. La más populares son:

  • Matplotlib: bajo nivel, alta personalización

  • Pandas visualización: contruida sobre Matplotlib, interfáz facil

  • Seaborn: interfaz de alto nivel, bonitos estilos de default

  • ggplot: basado en ggplo2 de R

  • Plotly: crea graficas interactivas

import pandas as pd
import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
from sklearn import datasets

Importamos los datos:

iris = pd.read_csv('iris.csv', names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class'],index_col=False)
iris.head()
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-2-b2d20165d81d> in <module>
----> 1 iris = pd.read_csv('iris.csv', names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class'],index_col=False)
      2 iris.head()

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)
    684     )
    685 
--> 686     return _read(filepath_or_buffer, kwds)
    687 
    688 

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds)
    450 
    451     # Create the parser.
--> 452     parser = TextFileReader(fp_or_buf, **kwds)
    453 
    454     if chunksize or iterator:

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in __init__(self, f, engine, **kwds)
    944             self.options["has_index_names"] = kwds["has_index_names"]
    945 
--> 946         self._make_engine(self.engine)
    947 
    948     def close(self):

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in _make_engine(self, engine)
   1176     def _make_engine(self, engine="c"):
   1177         if engine == "c":
-> 1178             self._engine = CParserWrapper(self.f, **self.options)
   1179         else:
   1180             if engine == "python":

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in __init__(self, src, **kwds)
   2006         kwds["usecols"] = self.usecols
   2007 
-> 2008         self._reader = parsers.TextReader(src, **kwds)
   2009         self.unnamed_cols = self._reader.unnamed_cols
   2010 

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader.__cinit__()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._setup_parser_source()

FileNotFoundError: [Errno 2] No such file or directory: 'iris.csv'
iris.head()
sepal_length sepal_width petal_length petal_width class
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

Importamos la segunda base:

wine_reviews = pd.read_csv('winemag-data-130k-v2.csv', index_col=0)
wine_reviews.head()
country description designation points price province region_1 region_2 taster_name taster_twitter_handle title variety winery
0 Italy Aromas include tropical fruit, broom, brimston... Vulkà Bianco 87 NaN Sicily & Sardinia Etna NaN Kerin O’Keefe @kerinokeefe Nicosia 2013 Vulkà Bianco (Etna) White Blend Nicosia
1 Portugal This is ripe and fruity, a wine that is smooth... Avidagos 87 15.0 Douro NaN NaN Roger Voss @vossroger Quinta dos Avidagos 2011 Avidagos Red (Douro) Portuguese Red Quinta dos Avidagos
2 US Tart and snappy, the flavors of lime flesh and... NaN 87 14.0 Oregon Willamette Valley Willamette Valley Paul Gregutt @paulgwine Rainstorm 2013 Pinot Gris (Willamette Valley) Pinot Gris Rainstorm
3 US Pineapple rind, lemon pith and orange blossom ... Reserve Late Harvest 87 13.0 Michigan Lake Michigan Shore NaN Alexander Peartree NaN St. Julian 2013 Reserve Late Harvest Riesling ... Riesling St. Julian
4 US Much like the regular bottling from 2012, this... Vintner's Reserve Wild Child Block 87 65.0 Oregon Willamette Valley Willamette Valley Paul Gregutt @paulgwine Sweet Cheeks 2012 Vintner's Reserve Wild Child... Pinot Noir Sweet Cheeks

Matplotlib

Matplotlib es una de la librerias más famosas. es de bajo nivel, esto implica que tendremos que escribir más pero podremos personalizar más nuestras graficas. Es particularmente utíl cuando queremos:

  • grafico de lineas

  • de barras

  • histogramas

Scatter Plot

Podemos crear directo el scatter o podemos crear una figura caracterizandola y personalizando los ejes con plt.subplots():

# creamos la figura y los ejes
plt.scatter(iris['sepal_length'], iris['sepal_width'])
<matplotlib.collections.PathCollection at 0x1e81ab8e088>
../../_images/Visualizacion_8_1.png

Ahora vamos a añadir unos detalles al plot para hacerlo mas comprensible:

fig, ax = plt.subplots()

ax.scatter(iris['sepal_length'], iris['sepal_width'])

ax.set_title('Iris Dataset')
ax.set_xlabel('Largo Petalo')
ax.set_ylabel('Ancho Petalo')
Text(0, 0.5, 'Ancho Petalo')
../../_images/Visualizacion_10_1.png

Podemos también plotear segun los colores de cada familia:

colors = {'setosa':'r', 'versicolor':'g', 'virginica':'b'}

fig, ax = plt.subplots()

for i in range(len(iris['sepal_length'])):
    ax.scatter(iris['sepal_length'][i], iris['sepal_width'][i],color=colors[iris['class'][i]])

    ax.set_title('Iris Dataset')
ax.set_xlabel('sepal_length')
ax.set_ylabel('sepal_width')
Text(0, 0.5, 'sepal_width')
../../_images/Visualizacion_12_1.png

Plot

Con la función plot podemos graficar nuestras graficas de lineas

x_data = range(0, iris.shape[0])
plt.plot(x_data, iris['sepal_width'])
[<matplotlib.lines.Line2D at 0x1e81d7d08c8>]
../../_images/Visualizacion_14_1.png

Podemos graficar más de uno a la vez:

# get columns to plot
columns = iris.columns.drop(['class'])
# create x data
x_data = range(0, iris.shape[0])
# create figure and axis
fig, ax = plt.subplots()
# plot each column
for column in columns:
    ax.plot(x_data, iris[column], label=column)
# set title and legend
ax.set_title('Iris Dataset')
ax.legend()
<matplotlib.legend.Legend at 0x1e81d728b88>
../../_images/Visualizacion_16_1.png

Histogramas

Con la función hist podemos crear histogramas. Cuando le pasamos una variable categorica en automatico nos calculará su frecuencia en el DB.

fig, ax = plt.subplots()

ax.hist(wine_reviews['points'])

ax.set_title('Puntaje de los vinos')
ax.set_xlabel('Puntaje')
ax.set_ylabel('Frecuencia')
Text(0, 0.5, 'Frecuencia')
../../_images/Visualizacion_18_1.png

Grafico de barras

Utilizando la función bar podemos crear una grafica de barra. En este caso no se calculará en automatico la frecuencia y por lo tanto tendremos que hacerlo manualmente nosotros. Este grafico funciona bien cuando no tenemos demasiadas variables categoricas (<30)

fig, ax = plt.subplots() 

# calculamos la frecuencia para cada categoria de datos 
data = wine_reviews['points'].value_counts() 

# definimos la x y la y
points = data.index 
frequency = data.values 

# creamos el grafico
ax.bar(points, frequency) 

ax.set_title('Puntajes Vinos') 
ax.set_xlabel('Puntos') 
ax.set_ylabel('Frecuencia')
Text(0, 0.5, 'Frecuencia')
../../_images/Visualizacion_20_1.png

Pandas

Ya conocemos las propriedades de panda en manejar dataframes, pero es también una buena herramienta para construir graficas. Construida sobre Matplotlib es de más alto nivel y por lo tanto necesitaremos menos codigos para construir nuestras graficas.

Por ejemplo:

Scatter plot

iris.plot.scatter(x='sepal_length', y='sepal_width', title='Iris Dataset')
<AxesSubplot:title={'center':'Iris Dataset'}, xlabel='sepal_length', ylabel='sepal_width'>
../../_images/Visualizacion_22_1.png

Grafico de Lineas

En ese caso no tendremos que hacer un loop para cada columna siendo que en automatico ploteará todas las columnas.

iris.drop(['class'], axis=1).plot.line(title='Iris Dataset')
<AxesSubplot:title={'center':'Iris Dataset'}>
../../_images/Visualizacion_24_1.png

Histogramas

No tenemos que pasarle ningun argumento aunque podamos especificar el ancho de los intervalos eventualmente

wine_reviews['points'].plot.hist()
<AxesSubplot:ylabel='Frequency'>
../../_images/Visualizacion_26_1.png
wine_reviews['points'].plot.hist(bins=30)
<AxesSubplot:ylabel='Frequency'>
../../_images/Visualizacion_27_1.png

Finalmente podemos crear multiples histogramas, con subplots especificamos que queremos un histograma para cada columna mientras en el layout especificamos como acomodarlos.

iris.plot.hist(subplots=True, layout=(2,2), figsize=(10, 10), bins=20)
array([[<AxesSubplot:ylabel='Frequency'>,
        <AxesSubplot:ylabel='Frequency'>],
       [<AxesSubplot:ylabel='Frequency'>,
        <AxesSubplot:ylabel='Frequency'>]], dtype=object)
../../_images/Visualizacion_29_1.png

Grafico de Barras

Cuando utilizamos el grafico de barras de nuevotendremos que contar los valores y luego ordenarlos del menor al mayor para poder obtener la grafica correcta.

wine_reviews['points'].value_counts().sort_index().plot.bar()
<AxesSubplot:>
../../_images/Visualizacion_31_1.png

Como vimos en la pasada clase podemos hacerlo también horizontal nuestro grafico:

wine_reviews['points'].value_counts().sort_index().plot.barh()
<AxesSubplot:>
../../_images/Visualizacion_33_1.png

Podemos tmabién plotear cosas que no son las frecuencias, agrupamos los datos por país y luego tomamos la media de esos:

wine_reviews.groupby("country").price.mean().sort_values(ascending=False)[:5].plot.bar()
<AxesSubplot:xlabel='country'>
../../_images/Visualizacion_35_1.png

Seaborn

Con seaborn podemos obtner lo mismo resultado vistos previamente, con un estilo diferente.

Scatter Plot

En este caso tendremos que especificar el DB desde que tomar los datos en cuanto no lo estamos llamando directamente:

sns.scatterplot(x='sepal_length', y='sepal_width', data=iris)
<AxesSubplot:xlabel='sepal_length', ylabel='sepal_width'>
../../_images/Visualizacion_37_1.png

Podemos también defini colores con respecto a algun grupo especifico:

sns.scatterplot(x='sepal_length', y='sepal_width', hue='class', data=iris)
<AxesSubplot:xlabel='sepal_length', ylabel='sepal_width'>
../../_images/Visualizacion_39_1.png

Grafico de Lineas

Podemos utilizar el clasico lineplot, al cual tendremos solo que pasar el dataframe o el kdeplo en presencia de muchos outliers, así de obtener un grafico más suave.

sns.lineplot(data=iris.drop(['class'], axis=1))
<AxesSubplot:>
../../_images/Visualizacion_41_1.png

Podemos plotear también la densidad:

sns.kdeplot(data=iris.drop(['class'], axis=1))
<AxesSubplot:ylabel='Density'>
../../_images/Visualizacion_43_1.png

Densidades

tips = sns.load_dataset("tips")
sns.kdeplot(data=tips, x="total_bill")
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_45_1.png

Podemos también cambiar el eje, imponiendo la y:

sns.kdeplot(data=tips, y="total_bill")
<AxesSubplot:xlabel='Density', ylabel='total_bill'>
../../_images/Visualizacion_47_1.png

Podemos ajustar el bandwith para obtener graficos mas o menos smooth:

sns.kdeplot(data=tips, x="total_bill", bw_adjust=.6)
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_49_1.png
sns.kdeplot(data=tips, x="total_bill", hue="time")
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_50_1.png

Podemos plotear las distintas categorias como vimos antes y stackearlas, osea sumarlas verticalmente:

sns.kdeplot(data=tips, x="total_bill", hue="time", multiple="stack")
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_52_1.png

Finalmente podemos normalizar a 100 la distribuciones stacked

sns.kdeplot(data=tips, x="total_bill", hue="time", multiple="fill")
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_54_1.png

Finalmente podemos crear una grafica cumulada, normalizando por cada grupo:

sns.kdeplot(
    data=tips, x="total_bill", hue="time",
    cumulative=True, common_norm=False, common_grid=True,
)
<AxesSubplot:xlabel='total_bill', ylabel='Density'>
../../_images/Visualizacion_56_1.png

Histogramas

en este caso tendremos que especificar que columna queremos plotear y por esa se calcularán las frecuencia. tenemos ademas especificar el numero de intervalos y, en el caso, si queremos plotear también la densidad del kernel gaussiano.

sns.distplot(wine_reviews['points'], bins=10, kde=False)
C:\ProgramData\Anaconda3\lib\site-packages\seaborn\distributions.py:2557: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).
  warnings.warn(msg, FutureWarning)
<AxesSubplot:xlabel='points'>
../../_images/Visualizacion_58_2.png
sns.distplot(wine_reviews['points'], bins=10, kde=True)
<AxesSubplot:xlabel='points', ylabel='Density'>
../../_images/Visualizacion_59_1.png

Grafico de barra

en este caso es suficiente pasar los datos que queremos graficar sin necesidad de hacer un conteo:

sns.countplot(wine_reviews['points'])
C:\ProgramData\Anaconda3\lib\site-packages\seaborn\_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning
<AxesSubplot:xlabel='points', ylabel='count'>
../../_images/Visualizacion_61_2.png

Boxplot

nos permite representar lo que en ingles definen como Five-number summay:

  • minimo

  • primer cuartil

  • mediana

  • tercer cuartil

  • maximo

df = wine_reviews[(wine_reviews['points']>=95) & (wine_reviews['price']<1000)]
sns.boxplot('points', 'price', data=df)
C:\ProgramData\Anaconda3\lib\site-packages\seaborn\_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning
<AxesSubplot:xlabel='points', ylabel='price'>
../../_images/Visualizacion_63_2.png

Mapas de calor

Un mapa de calor es una representación gráfica de datos donde los valores individuales contenidos en una matriz se representan como colores. Los mapas de calor son perfectos para explorar la correlación de características en un conjunto de datos.

La podemos hacer tanto con Matplotlib como con seaborn… pero hay diferencias:

# calculamos las correlaciones
corr = iris.corr()
fig, ax = plt.subplots()

im = ax.imshow(corr.values)


ax.set_xticks(np.arange(len(corr.columns)))
ax.set_yticks(np.arange(len(corr.columns)))
ax.set_xticklabels(corr.columns)
ax.set_yticklabels(corr.columns)

#rotamos las etiquetas
plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
         rotation_mode="anchor")

#hacemos un loop con respecto a las distintas dimensiones de los datos y creamos las notas de texco
for i in range(len(corr.columns)):
    for j in range(len(corr.columns)):
        text = ax.text(j, i, np.around(corr.iloc[i, j], decimals=2),
                       ha="center", va="center", color="black")
../../_images/Visualizacion_65_0.png
sns.heatmap(iris.corr(), annot=True)
<AxesSubplot:>
../../_images/Visualizacion_66_1.png

más facil….

Faceting

Es el acto de dividir los datos con respecto a distintos subplot y combinarlos en un unica figura. Es muy util tambien cuando queremos hacer una analisis exploratoria de los datos. En seaborn vamos a utilziar la función FacetGrid. Antes definimos la función con respecto al cual queremos descomponer el analisis y luego definimos la funcion map para definir el tipo de plot así como la caolumna (variable) que queremos definir. Documentación

g = sns.FacetGrid(iris, col='class')
g = g.map(sns.kdeplot, 'sepal_length')
../../_images/Visualizacion_68_0.png
db.groupby('response')['salary'].median()
response
no     60000
yes    60000
Name: salary, dtype: int64
g = sns.FacetGrid(tips, col="time",  row="sex")
g.map(sns.scatterplot, "total_bill", "tip")
<seaborn.axisgrid.FacetGrid at 0x1e829f3d348>
../../_images/Visualizacion_70_1.png
g = sns.FacetGrid(tips, col="time",  row="sex")
g.map_dataframe(sns.histplot, x="total_bill")
<seaborn.axisgrid.FacetGrid at 0x1e82a09d488>
../../_images/Visualizacion_71_1.png
g = sns.FacetGrid(tips, col="time", hue="sex")
g.map_dataframe(sns.scatterplot, x="total_bill", y="tip")
g.set_axis_labels("Total bill", "Tip")
g.add_legend()
<seaborn.axisgrid.FacetGrid at 0x1e82a0bdd08>
../../_images/Visualizacion_72_1.png
g = sns.FacetGrid(tips, col="sex", row="time", margin_titles=True, despine=False)
g.map_dataframe(sns.scatterplot, x="total_bill", y="tip")
g.set_axis_labels("Total bill", "Tip")
g.fig.subplots_adjust(wspace=0, hspace=0)
for (row_val, col_val), ax in g.axes_dict.items():
    if row_val == "Lunch" and col_val == "Female":
        ax.set_facecolor(".95")
    else:
        ax.set_facecolor((0, 0, 0, 0))
../../_images/Visualizacion_73_0.png

Pairplot

Por último, vemos el diagrama de pares de Seaborns y Pandas scatter_matrix, que permiten trazar una cuadrícula de relaciones por pares en un conjunto de datos. Estas técnicas siempre plotean dos características entre sí. La diagonal del gráfico está llena de histogramas y los otros gráficos son gráficos de dispersión.

sns.pairplot(iris)
<seaborn.axisgrid.PairGrid at 0x1e82a49f948>
../../_images/Visualizacion_75_1.png
from pandas.plotting import scatter_matrix

fig, ax = plt.subplots(figsize=(12,12))
scatter_matrix(iris, alpha=1, ax=ax)
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:4: UserWarning: To output multiple subplots, the figure containing the passed axes is being cleared
  after removing the cwd from sys.path.
array([[<AxesSubplot:xlabel='sepal_length', ylabel='sepal_length'>,
        <AxesSubplot:xlabel='sepal_width', ylabel='sepal_length'>,
        <AxesSubplot:xlabel='petal_length', ylabel='sepal_length'>,
        <AxesSubplot:xlabel='petal_width', ylabel='sepal_length'>],
       [<AxesSubplot:xlabel='sepal_length', ylabel='sepal_width'>,
        <AxesSubplot:xlabel='sepal_width', ylabel='sepal_width'>,
        <AxesSubplot:xlabel='petal_length', ylabel='sepal_width'>,
        <AxesSubplot:xlabel='petal_width', ylabel='sepal_width'>],
       [<AxesSubplot:xlabel='sepal_length', ylabel='petal_length'>,
        <AxesSubplot:xlabel='sepal_width', ylabel='petal_length'>,
        <AxesSubplot:xlabel='petal_length', ylabel='petal_length'>,
        <AxesSubplot:xlabel='petal_width', ylabel='petal_length'>],
       [<AxesSubplot:xlabel='sepal_length', ylabel='petal_width'>,
        <AxesSubplot:xlabel='sepal_width', ylabel='petal_width'>,
        <AxesSubplot:xlabel='petal_length', ylabel='petal_width'>,
        <AxesSubplot:xlabel='petal_width', ylabel='petal_width'>]],
      dtype=object)
../../_images/Visualizacion_76_2.png

Plotly

El paquete plotly Python existe para crear, manipular y renderizar figuras gráficas (es decir, tablas, diagramas, mapas y diagramas) representadas por estructuras de datos también denominadas figuras. El proceso de renderizado usa la biblioteca de JavaScript Plotly.js como bajo capa, aunque los desarrolladores de Python que usan este módulo rara vez necesitan interactuar con la biblioteca de Javascript directamente, si es que alguna vez lo hacen. Las figuras se pueden representar en Python como dictados o como instancias de la clase plotly.graph_objects.Figure, y se serializan como texto en JavaScript Object Notation (JSON) antes de pasar a Plotly.js.

import plotly.express as px

fig = px.line(x=["a","b","c"], y=[1,3,2], title="sample figure")
print(fig)
fig.show()
Figure({
    'data': [{'hovertemplate': 'x=%{x}<br>y=%{y}<extra></extra>',
              'legendgroup': '',
              'line': {'color': '#636efa', 'dash': 'solid'},
              'mode': 'lines',
              'name': '',
              'orientation': 'v',
              'showlegend': False,
              'type': 'scatter',
              'x': array(['a', 'b', 'c'], dtype=object),
              'xaxis': 'x',
              'y': array([1, 3, 2], dtype=int64),
              'yaxis': 'y'}],
    'layout': {'legend': {'tracegroupgap': 0},
               'template': '...',
               'title': {'text': 'sample figure'},
               'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'x'}},
               'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'y'}}}
})

Las figuras se organizan en diferentes niveles. En particular tendremos 3 niveles Top:

  • data

  • layout

  • frames

Finalmente podemos configurar más profundamente nuestras graficas aunque el plotly.express nos ofrece numerosas opciones predeterminadas.

df = px.data.stocks()
fig = px.line(df, x='date', y="GOOG")
fig.show()
df = px.data.stocks(indexed=True)-1
fig = px.bar(df, x=df.index, y="GOOG")
fig.show()
fig = px.area(df, facet_col="company", facet_col_wrap=2)
fig.show()
import plotly.express as px
df = px.data.stocks()
fig = px.line(df, x="date", y=df.columns,
              hover_data={"date": "|%B %d, %Y"},
              title='custom tick labels')
fig.update_xaxes(
    dtick="M1",
    tickformat="%b\n%Y")
fig.show()
import plotly.graph_objects as go

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig = px.histogram(df, x="Date", y="AAPL.Close", histfunc="avg", title="Histogram on Date Axes")
fig.update_traces(xbins_size="M1")
fig.update_xaxes(showgrid=True, ticklabelmode="period", dtick="M1", tickformat="%b\n%Y")
fig.update_layout(bargap=0.1)
fig.add_trace(go.Scatter(mode="markers", x=df["Date"], y=df["AAPL.Close"], name="daily"))
fig.show()
fig = px.line(df, x='Date', y='AAPL.High', title='Time Series with Rangeslider')

fig.update_xaxes(rangeslider_visible=True)
fig.show()
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species",
                 size='petal_length', hover_data=['petal_width'])
fig.show()
fig = go.Figure(data=go.Scatter(
    y = np.random.randn(500),
    mode='markers',
    marker=dict(
        size=16,
        color=np.random.randn(500), #set color equal to a variable
        colorscale='Viridis', # one of plotly colorscales
        showscale=True
    )
))

fig.show()
import math

# Load data, define hover text and bubble size
data = px.data.gapminder()
df_2007 = data[data['year']==2007]
df_2007 = df_2007.sort_values(['continent', 'country'])

hover_text = []
bubble_size = []

for index, row in df_2007.iterrows():
    hover_text.append(('Country: {country}<br>'+
                      'Life Expectancy: {lifeExp}<br>'+
                      'GDP per capita: {gdp}<br>'+
                      'Population: {pop}<br>'+
                      'Year: {year}').format(country=row['country'],
                                            lifeExp=row['lifeExp'],
                                            gdp=row['gdpPercap'],
                                            pop=row['pop'],
                                            year=row['year']))
    bubble_size.append(math.sqrt(row['pop']))

df_2007['text'] = hover_text
df_2007['size'] = bubble_size
sizeref = 2.*max(df_2007['size'])/(100**2)

# Dictionary with dataframes for each continent
continent_names = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania']
continent_data = {continent:df_2007.query("continent == '%s'" %continent)
                              for continent in continent_names}

# Create figure
fig = go.Figure()

for continent_name, continent in continent_data.items():
    fig.add_trace(go.Scatter(
        x=continent['gdpPercap'], y=continent['lifeExp'],
        name=continent_name, text=continent['text'],
        marker_size=continent['size'],
        ))

# Tune marker appearance and layout
fig.update_traces(mode='markers', marker=dict(sizemode='area',
                                              sizeref=sizeref, line_width=2))

fig.update_layout(
    title='Life Expectancy v. Per Capita GDP, 2007',
    xaxis=dict(
        title='GDP per capita (2000 dollars)',
        gridcolor='white',
        type='log',
        gridwidth=2,
    ),
    yaxis=dict(
        title='Life Expectancy (years)',
        gridcolor='white',
        gridwidth=2,
    ),
    paper_bgcolor='rgb(243, 243, 243)',
    plot_bgcolor='rgb(243, 243, 243)',
)
fig.show()
fig = go.Figure(data=go.Scatter(
        x=[1, 2, 3, 4],
        y=[2, 1, 3, 4],
        error_y=dict(
            type='data',
            symmetric=False,
            array=[0.1, 0.2, 0.1, 0.1],
            arrayminus=[0.2, 0.4, 1, 0.2])
        ))
fig.show()
schools = ["Brown", "NYU", "Notre Dame", "Cornell", "Tufts", "Yale",
           "Dartmouth", "Chicago", "Columbia", "Duke", "Georgetown",
           "Princeton", "U.Penn", "Stanford", "MIT", "Harvard"]

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=[72, 67, 73, 80, 76, 79, 84, 78, 86, 93, 94, 90, 92, 96, 94, 112],
    y=schools,
    marker=dict(color="crimson", size=12),
    mode="markers",
    name="Women",
))

fig.add_trace(go.Scatter(
    x=[92, 94, 100, 107, 112, 114, 114, 118, 119, 124, 131, 137, 141, 151, 152, 165],
    y=schools,
    marker=dict(color="gold", size=12),
    mode="markers",
    name="Men",
))

fig.update_layout(title="Gender Earnings Disparity",
                  xaxis_title="Annual Salary (in thousands)",
                  yaxis_title="School")

fig.show()
stages = ["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent"]
df_mtl = pd.DataFrame(dict(number=[39, 27.4, 20.6, 11, 3], stage=stages))
df_mtl['office'] = 'Montreal'
df_toronto = pd.DataFrame(dict(number=[52, 36, 18, 14, 5], stage=stages))
df_toronto['office'] = 'Toronto'
df = pd.concat([df_mtl, df_toronto], axis=0)
fig = px.funnel(df, x='number', y='stage', color='office')
fig.show()
df = px.data.medals_wide(indexed=True)
fig = px.imshow(df)
fig.show()
df = px.data.iris()
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
                    color='petal_length', symbol='species')
fig.show()
df = px.data.iris()
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
              color='petal_length', size='petal_length', size_max=18,
              symbol='species', opacity=0.7)

# tight layout
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')

fig = go.Figure(data=[go.Surface(z=z_data.values)])
fig.update_traces(contours_z=dict(show=True, usecolormap=True,
                                  highlightcolor="limegreen", project_z=True))
fig.update_layout(title='Mt Bruno Elevation', autosize=False,
                  scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),
                  width=500, height=500,
                  margin=dict(l=65, r=50, b=65, t=90)
)

fig.show()
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv')
df['text'] = df['airport'] + '' + df['city'] + ', ' + df['state'] + '' + 'Arrivals: ' + df['cnt'].astype(str)

fig = go.Figure(data=go.Scattergeo(
        lon = df['long'],
        lat = df['lat'],
        text = df['text'],
        mode = 'markers',
        marker_color = df['cnt'],
        ))

fig.update_layout(
        title = 'Most trafficked US airports<br>(Hover for airport names)',
        geo_scope='usa',
    )
fig.show()
from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)


df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                   dtype={"fips": str})

fig = px.choropleth_mapbox(df, geojson=counties, locations='fips', color='unemp',
                           color_continuous_scale="Viridis",
                           range_color=(0, 12),
                           mapbox_style="carto-positron",
                           zoom=3, center = {"lat": 37.0902, "lon": -95.7129},
                           opacity=0.5,
                           labels={'unemp':'unemployment rate'}
                          )
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
df = px.data.iris()
fig = px.parallel_coordinates(df, color="species_id", labels={"species_id": "Species",
                "sepal_width": "Sepal Width", "sepal_length": "Sepal Length",
                "petal_width": "Petal Width", "petal_length": "Petal Length", },
                             color_continuous_scale=px.colors.diverging.Tealrose,
                             color_continuous_midpoint=2)
fig.show()
df = px.data.gapminder().query("year == 2007")
df["world"] = "world" # in order to have a single root node
fig = px.treemap(df, path=['world', 'continent', 'country'], values='pop',
                  color='lifeExp', hover_data=['iso_alpha'],
                  color_continuous_scale='RdBu',
                  color_continuous_midpoint=np.average(df['lifeExp'], weights=df['pop']))
fig.show()
df = px.data.gapminder().query("year == 2007").query("continent == 'Europe'")
df.loc[df['pop'] < 2.e6, 'country'] = 'Other countries' # Represent only large countries
fig = px.pie(df, values='pop', names='country', title='Population of European continent')
fig.show()

Muchas veces necesitamos una llave para poder acceder a los datos que requerimos. Igual hay un verdadero mercado y sitio especializados para esto.

Por medio de los encabezaados HTTPS se manejan algunas informaciones sobre las APIs

response = requests.get("https://api.thedogapi.com/v1/breeds/1")
response.headers
{'Content-Encoding': 'gzip', 'Content-Type': 'application/json; charset=utf-8', 'Date': 'Fri, 07 May 2021 12:19:43 GMT', 'Server': 'Apache/2.4.46 (Amazon)', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains', 'Vary': 'Origin,Accept-Encoding', 'X-Content-Type-Options': 'nosniff', 'X-DNS-Prefetch-Control': 'off', 'X-Download-Options': 'noopen', 'X-Frame-Options': 'SAMEORIGIN', 'X-Response-Time': '2ms', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '265', 'Connection': 'keep-alive'}

Ya sabiendo que es un json, podemos acceder a el atravez de:

response.json()["name"]
'Affenpinscher'
endpoint = "https://www.googleapis.com/books/v1/volumes"
query = "la divina comedia"

params = {"q": query, "maxResults": 3}
response = requests.get(endpoint, params=params).json()
for book in response["items"]:
    volume = book["volumeInfo"]
    title = volume["title"]
    published = volume["authors"]
    print(f"{title} {published} ")
La Divina Comedia ['Dante Alighieri'] 
La divina comedia ['Dante Alghieri'] 
La Divina Comedia por Dante Alighieri ['Dante Alighieri'] 
response
{'kind': 'books#volumes',
 'totalItems': 734,
 'items': [{'kind': 'books#volume',
   'id': 'WrPCDwAAQBAJ',
   'etag': 'j6ynahmNPaE',
   'selfLink': 'https://www.googleapis.com/books/v1/volumes/WrPCDwAAQBAJ',
   'volumeInfo': {'title': 'La Divina Comedia',
    'authors': ['Dante Alighieri'],
    'publisher': 'Good Press',
    'publishedDate': '2019-11-11',
    'description': '"La Divina Comedia" de Dante Alighieri (traducido por Manuel Aranda y Sanjuan) de la Editorial Good Press. Good Press publica una gran variedad de títulos que abarca todos los géneros. Van desde los títulos clásicos famosos, novelas, textos documentales y crónicas de la vida real, hasta temas ignorados o por ser descubiertos de la literatura universal. Editorial Good Press divulga libros que son una lectura imprescindible. Cada publicación de Good Press ha sido corregida y formateada al detalle, para elevar en gran medida su facilidad de lectura en todos los equipos y programas de lectura electrónica. Nuestra meta es la producción de Libros electrónicos que sean versátiles y accesibles para el lector y para todos, en un formato digital de alta calidad.',
    'industryIdentifiers': [{'type': 'OTHER',
      'identifier': 'EAN:4057664122674'}],
    'readingModes': {'text': True, 'image': True},
    'pageCount': 941,
    'printType': 'BOOK',
    'categories': ['Fiction'],
    'maturityRating': 'NOT_MATURE',
    'allowAnonLogging': True,
    'contentVersion': '1.5.5.0.preview.3',
    'panelizationSummary': {'containsEpubBubbles': False,
     'containsImageBubbles': False},
    'imageLinks': {'smallThumbnail': 'http://books.google.com/books/content?id=WrPCDwAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api',
     'thumbnail': 'http://books.google.com/books/content?id=WrPCDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
    'language': 'es',
    'previewLink': 'http://books.google.com.mx/books?id=WrPCDwAAQBAJ&pg=PP1&dq=la+divina+comedia&hl=&cd=1&source=gbs_api',
    'infoLink': 'https://play.google.com/store/books/details?id=WrPCDwAAQBAJ&source=gbs_api',
    'canonicalVolumeLink': 'https://play.google.com/store/books/details?id=WrPCDwAAQBAJ'},
   'saleInfo': {'country': 'MX',
    'saleability': 'FOR_SALE',
    'isEbook': True,
    'listPrice': {'amount': 25, 'currencyCode': 'MXN'},
    'retailPrice': {'amount': 25, 'currencyCode': 'MXN'},
    'buyLink': 'https://play.google.com/store/books/details?id=WrPCDwAAQBAJ&rdid=book-WrPCDwAAQBAJ&rdot=1&source=gbs_api',
    'offers': [{'finskyOfferType': 1,
      'listPrice': {'amountInMicros': 25000000, 'currencyCode': 'MXN'},
      'retailPrice': {'amountInMicros': 25000000, 'currencyCode': 'MXN'},
      'giftable': True}]},
   'accessInfo': {'country': 'MX',
    'viewability': 'PARTIAL',
    'embeddable': True,
    'publicDomain': False,
    'textToSpeechPermission': 'ALLOWED',
    'epub': {'isAvailable': True},
    'pdf': {'isAvailable': True},
    'webReaderLink': 'http://play.google.com/books/reader?id=WrPCDwAAQBAJ&hl=&printsec=frontcover&source=gbs_api',
    'accessViewStatus': 'SAMPLE',
    'quoteSharingAllowed': False},
   'searchInfo': {'textSnippet': '&quot;La Divina Comedia&quot; de Dante Alighieri (traducido por Manuel Aranda y Sanjuan) de la Editorial Good Press.'}},
  {'kind': 'books#volume',
   'id': 'wGPSDgAAQBAJ',
   'etag': 'NOQVX9XaqiA',
   'selfLink': 'https://www.googleapis.com/books/v1/volumes/wGPSDgAAQBAJ',
   'volumeInfo': {'title': 'La divina comedia',
    'subtitle': '',
    'authors': ['Dante Alghieri'],
    'publisher': 'NoBooks Editorial',
    'publishedDate': '1976',
    'readingModes': {'text': True, 'image': True},
    'pageCount': 441,
    'printType': 'BOOK',
    'maturityRating': 'NOT_MATURE',
    'allowAnonLogging': True,
    'contentVersion': 'preview-1.0.0',
    'panelizationSummary': {'containsEpubBubbles': False,
     'containsImageBubbles': False},
    'imageLinks': {'smallThumbnail': 'http://books.google.com/books/content?id=wGPSDgAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api',
     'thumbnail': 'http://books.google.com/books/content?id=wGPSDgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
    'language': 'es',
    'previewLink': 'http://books.google.com.mx/books?id=wGPSDgAAQBAJ&printsec=frontcover&dq=la+divina+comedia&hl=&cd=2&source=gbs_api',
    'infoLink': 'https://play.google.com/store/books/details?id=wGPSDgAAQBAJ&source=gbs_api',
    'canonicalVolumeLink': 'https://play.google.com/store/books/details?id=wGPSDgAAQBAJ'},
   'saleInfo': {'country': 'MX',
    'saleability': 'FOR_SALE',
    'isEbook': True,
    'listPrice': {'amount': 28.84, 'currencyCode': 'MXN'},
    'retailPrice': {'amount': 28.84, 'currencyCode': 'MXN'},
    'buyLink': 'https://play.google.com/store/books/details?id=wGPSDgAAQBAJ&rdid=book-wGPSDgAAQBAJ&rdot=1&source=gbs_api',
    'offers': [{'finskyOfferType': 1,
      'listPrice': {'amountInMicros': 28840000, 'currencyCode': 'MXN'},
      'retailPrice': {'amountInMicros': 28840000, 'currencyCode': 'MXN'},
      'giftable': True}]},
   'accessInfo': {'country': 'MX',
    'viewability': 'PARTIAL',
    'embeddable': True,
    'publicDomain': False,
    'textToSpeechPermission': 'ALLOWED',
    'epub': {'isAvailable': True},
    'pdf': {'isAvailable': True},
    'webReaderLink': 'http://play.google.com/books/reader?id=wGPSDgAAQBAJ&hl=&printsec=frontcover&source=gbs_api',
    'accessViewStatus': 'SAMPLE',
    'quoteSharingAllowed': False}},
  {'kind': 'books#volume',
   'id': 'O0ESIQu9_7wC',
   'etag': 'bzi0xAGR2sk',
   'selfLink': 'https://www.googleapis.com/books/v1/volumes/O0ESIQu9_7wC',
   'volumeInfo': {'title': 'La Divina Comedia por Dante Alighieri',
    'subtitle': 'El Infierno',
    'authors': ['Dante Alighieri'],
    'publishedDate': '1870',
    'industryIdentifiers': [{'type': 'OTHER',
      'identifier': 'IBNF:CF005685501'}],
    'readingModes': {'text': False, 'image': False},
    'pageCount': 232,
    'printType': 'BOOK',
    'maturityRating': 'NOT_MATURE',
    'allowAnonLogging': False,
    'contentVersion': '0.2.1.0.preview.0',
    'panelizationSummary': {'containsEpubBubbles': False,
     'containsImageBubbles': False},
    'imageLinks': {'smallThumbnail': 'http://books.google.com/books/content?id=O0ESIQu9_7wC&printsec=frontcover&img=1&zoom=5&source=gbs_api',
     'thumbnail': 'http://books.google.com/books/content?id=O0ESIQu9_7wC&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
    'language': 'es',
    'previewLink': 'http://books.google.com.mx/books?id=O0ESIQu9_7wC&q=la+divina+comedia&dq=la+divina+comedia&hl=&cd=3&source=gbs_api',
    'infoLink': 'http://books.google.com.mx/books?id=O0ESIQu9_7wC&dq=la+divina+comedia&hl=&source=gbs_api',
    'canonicalVolumeLink': 'https://books.google.com/books/about/La_Divina_Comedia_por_Dante_Alighieri.html?hl=&id=O0ESIQu9_7wC'},
   'saleInfo': {'country': 'MX',
    'saleability': 'NOT_FOR_SALE',
    'isEbook': False},
   'accessInfo': {'country': 'MX',
    'viewability': 'NO_PAGES',
    'embeddable': False,
    'publicDomain': False,
    'textToSpeechPermission': 'ALLOWED',
    'epub': {'isAvailable': False},
    'pdf': {'isAvailable': False},
    'webReaderLink': 'http://play.google.com/books/reader?id=O0ESIQu9_7wC&hl=&printsec=frontcover&source=gbs_api',
    'accessViewStatus': 'NONE',
    'quoteSharingAllowed': False}}]}

Fuentes: