Gráficos Interactivos con Bokeh

Introducción:

Hola amigos de Internet, bienvenidos a Mi Diario Python, el mejor blog para Aprender Python.
En este articulo le daremos un vistazo a Boken, una librería que nos permite graficar datos de manera muy interactivo.
Y al final, veremos como generar una tabla periódica con Bokeh.
Así que prepárate, sírvete una taza de café, y comencemos.

Instalación de Bokeh:

Antes de graficar nuestros datos, necesitamos instalar Bokeh. Esto lo podemos hacer de manera muy fácil a través de pip:
pip install bokeh

Y listo, ya podremos empezar con la acción.

Ejemplos con Bokeh:

Realicemos un ejemplo sencillo. Hagamos la gráfica de linea:
from bokeh.plotting import figure, output_file, show

# Preparamos los datos
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

# Salida estática HTML
output_file("lines.html")

# Creamos un nuevo gráfico con un titulo y dos ejes (x e y)
p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

# Agregamos la linea con los datos
p.line(x, y, legend="Temp.", line_width=2)

# Mostramos el resultado
show(p)
Muy bien, como pueden observar el resultado es un cuerpo HTML el cual podemos mover e interactuar con el.

Realicemos otro ejemplo, esta vez con más lineas:

from bokeh.plotting import figure, output_file, show

# Preparamos los datos
x = [0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
y0 = [i**2 for i in x]
y1 = [10**i for i in x]
y2 = [10**(i**2) for i in x]

# Salida de un HTML 
output_file("log_lines.html")

# Creamos un nuevo gráfico
p = figure(
   tools="pan,box_zoom,reset,save",
   y_axis_type="log", y_range=[0.001, 10**11], title="log axis example",
   x_axis_label='sections', y_axis_label='particles'
)

# Agregamos las lineas, la cuales representaran a los datos
p.line(x, x, legend="y=x")
p.circle(x, x, legend="y=x", fill_color="white", size=8)
p.line(x, y0, legend="y=x^2", line_width=3)
p.line(x, y1, legend="y=10^x", line_color="red")
p.circle(x, y1, legend="y=10^x", fill_color="red", line_color="red", size=6)
p.line(x, y2, legend="y=10^x^2", line_color="orange", line_dash="4 4")

# Mostramos el resultado
show(p)
Como pueden observar, en este ejemplo utilizamos, ademas de "line", el método "circle" para que los datos sean representados con círculos, ademas de lineas.
Se ve bien ¿No lo crees? Pero creo que le falta un poco de color. 
Hago un ejemplo para ver como graficar datos coloridos.
import numpy as np

from bokeh.plotting import figure, output_file, show

# Preparamos los datos
N = 4000
x = np.random.random(size=N) * 100
y = np.random.random(size=N) * 100
radii = np.random.random(size=N) * 1.5
colors = [
    "#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50+2*x, 30+2*y)
]

# Salida de un archivo HTML
output_file("color_scatter.html", title="color_scatter.py example", mode="cdn")
# Herramientas que podremos ver en el lado derecho del gráfico)
TOOLS = "crosshair,pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"

# Creamos un nuevo gráfico con las herramientas
p = figure(tools=TOOLS, x_range=(0, 100), y_range=(0, 100))

# Agregamos el circulo con colores y tamaño vectorizado
p.circle(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None)

# Mostramos los resultados
show(p)
Excelente, mucho mejor.
En muchas ocasiones se nos presentara la situación en la que tendremos que presentar más de un gráfico. Para ello vamos a utilizar el método ""ColumnDataSource", el cual nos permitirá colocar más de un gráfico en una columna. Veamos como se hace:
import numpy as np
from bokeh.plotting import *
from bokeh.models import ColumnDataSource

# Preparamos los datos
N = 300
x = np.linspace(0, 4*np.pi, N)
y0 = np.sin(x)
y1 = np.cos(x)

# Salida de una archivo HTML
output_file("linked_brushing.html")

# Creamos las columnas para compartir varios gráficos
source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1))

TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"

# Creamos el primer gráfico
left = figure(tools=TOOLS, width=350, height=350, title=None)
left.circle('x', 'y0', source=source)

# Creamos el segundo gráfico
right = figure(tools=TOOLS, width=350, height=350, title=None)
right.circle('x', 'y1', source=source)

# colocamos los sub-gráficos con gridplot
p = gridplot([[left, right]])

# Mostramos el resultado
show(p)
Muy bien, perfecto, quedo genial.
Te recomiendo ir a la pagina de Bokeh pra que te vuelvas todo un experto: https://bokeh.pydata.org.

Generando una Tabla Periódica con Bokeh:

Para terminar este articulo, he escogido uno de los mejores ejemplo. Vamos a generar una tabla periódica con Boken. Veres que es muy sencillo:
from bokeh.io import output_file, show
from bokeh.plotting import figure
from bokeh.sampledata.periodic_table import elements
from bokeh.transform import dodge, factor_cmap

output_file("periodic.html")

periods = ["I", "II", "III", "IV", "V", "VI", "VII"]
groups = [str(x) for x in range(1, 19)]

df = elements.copy()
df["atomic mass"] = df["atomic mass"].astype(str)
df["group"] = df["group"].astype(str)
df["period"] = [periods[x-1] for x in df.period]
df = df[df.group != "-"]
df = df[df.symbol != "Lr"]
df = df[df.symbol != "Lu"]

cmap = {
    "alkali metal"         : "#a6cee3",
    "alkaline earth metal" : "#1f78b4",
    "metal"                : "#d93b43",
    "halogen"              : "#999d9a",
    "metalloid"            : "#e08d49",
    "noble gas"            : "#eaeaea",
    "nonmetal"             : "#f1d4Af",
    "transition metal"     : "#599d7A",
}

TOOLTIPS = [
    ("Name", "@name"),
    ("Atomic number", "@{atomic number}"),
    ("Atomic mass", "@{atomic mass}"),
    ("Type", "@metal"),
    ("CPK color", "$color[hex, swatch]:CPK"),
    ("Electronic configuration", "@{electronic configuration}"),
]

p = figure(title="Periodic Table (omitting LA and AC Series)", plot_width=1000, plot_height=450,
           x_range=groups, y_range=list(reversed(periods)),
           tools="hover", toolbar_location=None, tooltips=TOOLTIPS)

p.rect("group", "period", 0.95, 0.95, source=df, fill_alpha=0.6, legend="metal",
       color=factor_cmap('metal', palette=list(cmap.values()), factors=list(cmap.keys())))

text_props = {"source": df, "text_align": "left", "text_baseline": "middle"}

x = dodge("group", -0.4, range=p.x_range)

r = p.text(x=x, y="period", text="symbol", **text_props)
r.glyph.text_font_style="bold"

r = p.text(x=x, y=dodge("period", 0.3, range=p.y_range), text="atomic number", **text_props)
r.glyph.text_font_size="8pt"

r = p.text(x=x, y=dodge("period", -0.35, range=p.y_range), text="name", **text_props)
r.glyph.text_font_size="5pt"

r = p.text(x=x, y=dodge("period", -0.2, range=p.y_range), text="atomic mass", **text_props)
r.glyph.text_font_size="5pt"

p.text(x=["3", "3"], y=["VI", "VII"], text=["LA", "AC"], text_align="center", text_baseline="middle")

p.outline_line_color = None
p.grid.grid_line_color = None
p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_standoff = 0
p.legend.orientation = "horizontal"
p.legend.location ="top_center"

show(p)
Increíble, es genial.
Puedes encontrar este y otros ejemplo en la galería de Bokeh: https://bokeh.pydata.org/en/latest/docs/gallery/.
¿Alguna duda? No dudes en dejar tu comentario.
Mi nombre es Luis, y fue un placer compartir mis conocimientos con todos ustedes :D.
  1. Unknown dice:

    Hola, una pregunta y espero que puedas responderla, me gusto mucho esta herramienta quisiera saber si existe la posibilidad por ejemplo que al dar clic en una parte del gráfico me muestre algo, lo que sea, no sé por ejemplo en la gráfica de la tabla periódica que al dar clic por ejemplo en Hidrógeno, realice algo como ir a un link, o cargar más información etc.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir
White Monkey