{"id":746,"date":"2019-01-31T12:15:13","date_gmt":"2019-01-31T11:15:13","guid":{"rendered":"http:\/\/35.180.88.53\/?p=746"},"modified":"2019-10-28T13:39:54","modified_gmt":"2019-10-28T12:39:54","slug":"interactive-data-visualization-with-python-using-bokeh","status":"publish","type":"post","link":"https:\/\/www.sergilehkyi.com\/es\/2019\/01\/interactive-data-visualization-with-python-using-bokeh\/","title":{"rendered":"Visualizaci\u00f3n interactiva de datos con Python usando Bokeh"},"content":{"rendered":"\n<p>Recientemente encontr\u00e9 \u00e9sta biblioteca, aprend\u00ed un poco sobre ella, la prob\u00e9, por supuesto, y decid\u00ed compartir mis pensamientos.<\/p>\n\n\n\n<p>Desde el sitio web oficial: \u201cBokeh es una biblioteca de visualizaci\u00f3n interactiva que se dirige a los navegadores web modernos para la presentaci\u00f3n. Su objetivo es proporcionar una construcci\u00f3n elegante y concisa de gr\u00e1ficos vers\u00e1tiles, y extender esta capacidad con interactividad de alto rendimiento en conjuntos de datos muy grandes o de transmisi\u00f3n por secuencias. Bokeh puede ayudar a cualquier persona que quiera crear parcelas interactivas, paneles y aplicaciones de datos de forma r\u00e1pida y sencilla.&#8221; Creo que la explicaci\u00f3n es bastante clara, pero ser\u00eda mejor verlo en acci\u00f3n, \u00bfno?<\/p>\n\n\n\n<p>Antes de comenzar, aseg\u00farese de tener Bokeh instalado en tu entorno; si no lo tienes, siga las instrucciones de instalaci\u00f3n <a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/installation.html\">aqu\u00ed<\/a>.<\/p>\n\n\n\n<p>Cre\u00e9 alg\u00fan tipo de estudio de caso para m\u00ed mismo. Decidi\u00f3 visualizar los cambios en las emisiones de CO2 en el tiempo y en correlaci\u00f3n con el PIB (y comprobar si existe esa correlaci\u00f3n, porque nunca se sabe \ud83d\ude10 ).<\/p>\n\n\n\n<p>As\u00ed que tom\u00e9 dos archivos: uno con emisiones de CO2 de <a href=\"https:\/\/www.gapminder.org\/data\/\">Gapminder.org<\/a> y otro del curso en DataCamp (porque ese archivo ya estaba preprocesado \ud83d\ude00 yeeeeees, soy un bastardo perezoso \ud83d\ude00 ). Tambi\u00e9n puedes descargar estos archivos desde aqu\u00ed.<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"http:\/\/35.180.88.53\/wp-content\/uploads\/2019\/01\/co2_emissions_tonnes_per_person.csv\">co2_emissions_tonnes_per_person<\/a><a href=\"http:\/\/35.180.88.53\/wp-content\/uploads\/2019\/01\/co2_emissions_tonnes_per_person.csv\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"http:\/\/35.180.88.53\/wp-content\/uploads\/2019\/01\/gapminder_tidy.csv\">gapminder_tidy<\/a><a href=\"http:\/\/35.180.88.53\/wp-content\/uploads\/2019\/01\/gapminder_tidy.csv\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p>\u00bfC\u00f3mo empezamos a analizar los datos? Correcto, importando los paquetes necesarios e importando los datos mismos (muy importante :D). Luego realizamos un an\u00e1lisis exploratorio de datos (EDA, por sus siglas en ingl\u00e9s) para comprender con qu\u00e9 estamos trabajando y despu\u00e9s de eso, limpiar y transformar los datos en el formato necesario para el an\u00e1lisis. Muy claro. Como el art\u00edculo no se centra en estos pasos, solo insertar\u00e9 el c\u00f3digo a continuaci\u00f3n con todas las transformaciones que he realizado.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import pandas as pd<br>import numpy as np<br><br># Data cleaning and preparation<br>data = pd.read_csv('data\/co2_emissions_tonnes_per_person.csv')<br>data.head()<br><br>gapminder = pd.read_csv('data\/gapminder_tidy.csv')<br>gapminder.head()<br><br>df = gapminder[['Country', 'region']].drop_duplicates()<br>data_with_regions = pd.merge(data, df, left_on='country', right_on='Country', how='inner')<br>data_with_regions = data_with_regions.drop('Country', axis='columns')<br>data_with_regions.head()<br><br>new_df = pd.melt(data_with_regions, id_vars=['country', 'region'])<br>new_df.head()<br><br>columns = ['country', 'region', 'year', 'co2']<br>new_df.columns = columns<br><br>upd_new_df = new_df[new_df['year'].astype('int64') > 1963]<br>upd_new_df.info()<br>upd_new_df = upd_new_df.sort_values(by=['country', 'year'])<br>upd_new_df['year'] = upd_new_df['year'].astype('int64')<br><br>df_gdp = gapminder[['Country', 'Year', 'gdp']]<br>df_gdp.columns = ['country', 'year', 'gdp']<br>df_gdp.info()<br><br>final_df = pd.merge(upd_new_df, df_gdp, on=['country', 'year'], how='left')<br>final_df = final_df.dropna()<br>final_df.head()<br><br>np_co2 = np.array(final_df['co2'])<br>np_gdp = np.array(final_df['gdp'])<br>np.corrcoef(np_co2, np_gdp)<\/pre>\n\n\n\n<p>Por cierto, las emisiones de CO2 y el PIB se correlacionan, y de manera bastante significativa, de 0,78.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">np.corrcoef(np_co2, np_gdp)<br> Out[138]: <br> array([[1.        , 0.78219731],<br>        [0.78219731, 1.        ]])<\/pre>\n\n\n\n<p>Y ahora vamos a la parte de la visualizaci\u00f3n. Nuevamente, comenzamos con las importaciones necesarias. Les explicar\u00e9 todos durante el articulo. Ahora, solo rel\u00e1jate e importa.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">from bokeh.io import curdoc<br>from bokeh.plotting import figure<br>from bokeh.models import HoverTool, ColumnDataSource, CategoricalColorMapper, Slider<br>from bokeh.palettes import Spectral6<br>from bokeh.layouts import widgetbox, row<\/pre>\n\n\n\n<p>Comenzaremos con una preparaci\u00f3n de diferentes detalles para nuestra aplicaci\u00f3n de visualizaci\u00f3n interactiva. Primero, creamos un mapeador de colores para diferentes regiones del mundo, por lo que cada pa\u00eds tendr\u00e1 un color diferente dependiendo de la regi\u00f3n en la que se encuentre. Seleccionamos regiones \u00fanicas y las convertimos en una lista. Luego usamos CategoricalColorMapper para asignar un color diferente para cada regi\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">regions_list = final_df.region.unique().tolist()<br>color_mapper = CategoricalColorMapper(factors=regions_list, palette=Spectral6)<\/pre>\n\n\n\n<p>A continuaci\u00f3n, prepararemos una fuente de datos para nuestra aplicaci\u00f3n. Bokeh acepta una gran cantidad de diferentes tipos de datos como fuente de gr\u00e1ficos y elementos visuales: proporciona datos directamente utilizando listas de valores, marcos de datos y series de pandas, matrices de n\u00fameros y as\u00ed sucesivamente. Pero el n\u00facleo de la mayor\u00eda de los gr\u00e1ficos de Bokeh es ColumnDataSource.<\/p>\n\n\n\n<p>En el nivel m\u00e1s b\u00e1sico, un objeto <a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/sources.html#bokeh.models.sources.ColumnDataSource\"><code>ColumnDataSource<\/code><\/a> es simplemente una asignaci\u00f3n entre los nombres de las columnas y las listas de datos. <a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/sources.html#bokeh.models.sources.ColumnDataSource\"><code>ColumnDataSource<\/code><\/a> toma un par\u00e1metro <code>data<\/code> que es un dict, con nombres de columna de cadena como claves y listas (o matrices) de valores de datos como valores. Si se pasa un argumento posicional al inicializador <a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/sources.html#bokeh.models.sources.ColumnDataSource\"><code>ColumnDataSource<\/code><\/a>, se tomar\u00e1 como <code>data<\/code>. (desde el sitio web oficial).<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Make the ColumnDataSource: source<br>source = ColumnDataSource(data={<br>    'x': final_df.gdp[final_df['year'] == 1964],<br>    'y': final_df.co2[final_df['year'] == 1964],<br>    'country': final_df.country[final_df['year'] == 1964],<br>    'region': final_df.region[final_df['year'] == 1964],<br>})<\/pre>\n\n\n\n<p>Comenzamos con una muestra de nuestros datos solo por un a\u00f1o. B\u00e1sicamente creamos un diccionario de valores para x, y, pa\u00eds y regi\u00f3n.<\/p>\n\n\n\n<p>El siguiente paso es establecer l\u00edmites para nuestros ejes. Podemos hacerlo encontrando valores m\u00ednimos y m\u00e1ximos para x e y.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Save the minimum and maximum values of the gdp column: xmin, xmax<br>xmin, xmax = min(final_df.gdp), max(final_df.gdp)<br><br># Save the minimum and maximum values of the co2 column: ymin, ymax<br>ymin, ymax = min(final_df.co2), max(final_df.co2)<\/pre>\n\n\n\n<p>Despu\u00e9s de eso creamos nuestra figura, donde colocaremos todos nuestros objetos de visualizaci\u00f3n. Le damos un t\u00edtulo, ajuste el ancho y la altura y tambi\u00e9n establecemos los ejes. (El eje <code>Y<\/code> est\u00e1 configurado del tipo <code>'log'<\/code> solo para una mejor vista; se probaron unos tipos y este dio el mejor resultado)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Create the figure: plot<br>plot = figure(title='Gapminder Data for 1964', <br>              plot_height=600, plot_width=1000,<br>              x_range=(xmin, xmax),<br>              y_range=(ymin, ymax), y_axis_type='log')<\/pre>\n\n\n\n<p>Bokeh usa una definici\u00f3n de glifo para todas las formas visuales que pueden aparecer en la trama. La lista completa de glifos incorporados en Bokeh se presenta a continuaci\u00f3n (sin inventar nada, toda la informaci\u00f3n de la p\u00e1gina oficial):<\/p>\n\n\n\n<ul><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/annular_wedge.html#bokeh.models.glyphs.AnnularWedge\"><code>AnnularWedge<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/annulus.html#bokeh.models.glyphs.Annulus\"><code>Annulus<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/arc.html#bokeh.models.glyphs.Arc\"><code>Arc<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/bezier.html#bokeh.models.glyphs.Bezier\"><code>Bezier<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/ellipse.html#bokeh.models.glyphs.Ellipse\"><code>Ellipse<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/hbar.html#bokeh.models.glyphs.HBar\"><code>HBar<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/hex_tile.html#bokeh.models.glyphs.HexTile\"><code>HexTile<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/image.html#bokeh.models.glyphs.Image\"><code>Image<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/image_rgba.html#bokeh.models.glyphs.ImageRGBA\"><code>ImageRGBA<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/image_url.html#bokeh.models.glyphs.ImageURL\"><code>ImageURL<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/line.html#bokeh.models.glyphs.Line\"><code>Line<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/multi_line.html#bokeh.models.glyphs.MultiLine\"><code>MultiLine<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/multi_polygons.html#bokeh.models.glyphs.MultiPolygons\"><code>MultiPolygons<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/oval.html#bokeh.models.glyphs.Oval\"><code>Oval<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/patch.html#bokeh.models.glyphs.Patch\"><code>Patch<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/patches.html#bokeh.models.glyphs.Patches\"><code>Patches<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/quad.html#bokeh.models.glyphs.Quad\"><code>Quad<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/quadratic.html#bokeh.models.glyphs.Quadratic\"><code>Quadratic<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/ray.html#bokeh.models.glyphs.Ray\"><code>Ray<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/rect.html#bokeh.models.glyphs.Rect\"><code>Rect<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/segment.html#bokeh.models.glyphs.Segment\"><code>Segment<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/step.html#bokeh.models.glyphs.Step\"><code>Step<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/text.html#bokeh.models.glyphs.Text\"><code>Text<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/vbar.html#bokeh.models.glyphs.VBar\"><code>VBar<\/code><\/a><\/li><li><a href=\"https:\/\/bokeh.pydata.org\/en\/latest\/docs\/reference\/models\/glyphs\/wedge.html#bokeh.models.glyphs.Wedge\"><code>Wedge<\/code><\/a><\/li><\/ul>\n\n\n\n<p>Todos estos glifos comparten una interfaz m\u00ednima com\u00fan a trav\u00e9s de su clase base <code>Glyph<\/code> <\/p>\n\n\n\n<p>No vamos a profundizar demasiado con todas estas formas y usaremos los c\u00edrculos como una de las m\u00e1s b\u00e1sicas. Si deseas jugar m\u00e1s con otros glifos, tienes toda la documentaci\u00f3n y los enlaces necesarios.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Add circle glyphs to the plot<br>plot.circle(x='x', y='y', fill_alpha=0.8, source=source, legend='region',<br>            color=dict(field='region', transform=color_mapper),<br>            size=7)<\/pre>\n\n\n\n<p>Entonces, \u00bfc\u00f3mo a\u00f1adimos estos c\u00edrculos? Asignamos nuestra fuente al par\u00e1metro &#8220;source&#8221; del glifo de c\u00edrculo, especificamos datos para x e y, agregamos leyenda para los colores y aplicamos ColorMapper creado previamente al par\u00e1metro &#8220;color&#8221;, &#8220;fill_alpha&#8221; establece un poco de transparencia y &#8220;Tama\u00f1o&#8221; es el tama\u00f1o de los c\u00edrculos que aparecer\u00e1n en la trama.<\/p>\n\n\n\n<p>A continuaci\u00f3n, agregamos afinar el aspecto de nuestra trama configurando la ubicaci\u00f3n de la leyenda y dando algunas explicaciones a nuestros ejes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Set the legend.location attribute of the plot<br>plot.legend.location = 'bottom_right'<br><br># Set the x-axis label<br>plot.xaxis.axis_label = 'Income per person (Gross domestic product per person adjusted for differences in ' <br>purchasing power in international dollars, fixed 2011 prices, PPP based on 2011 ICP)'<br><br># Set the y-axis label<br>plot.yaxis.axis_label = 'CO2 emissions (tonnes per person)'<\/pre>\n\n\n\n<p>A partir de ahora tenemos un gr\u00e1fico b\u00e1sico y est\u00e1tico para el a\u00f1o 1964, pero el t\u00edtulo del art\u00edculo tiene una palabra que no encaja con esta situaci\u00f3n &#8211; &#8220;Interactiva&#8221; O_O. \u00a1As\u00ed que vamos a a\u00f1adir un poco de interactividad!<\/p>\n\n\n\n<p>Para ello, agregaremos un slider con a\u00f1os, por lo que al final tendremos una visualizaci\u00f3n para cada a\u00f1o disponible. \u00a1Guay! \u00bfno es as\u00ed?<\/p>\n\n\n\n<p>Anteriormente import\u00e1bamos la clase Slider, \u00a1ahora es el momento de usarlo! As\u00ed que creamos el objeto de esta clase, siendo el a\u00f1o m\u00ednimo, final, m\u00e1ximo, valor predeterminado &#8211; a\u00f1o m\u00ednimo nuevamente, paso (qu\u00e9 tan r\u00e1pido est\u00e1n cambiando los valores en el slider) &#8211; 1 a\u00f1o y el t\u00edtulo.<\/p>\n\n\n\n<p>Tambi\u00e9n creamos un callback para cualquier cambio que ocurra en este slider. Los callbacks en Bokeh siempre tienen los mismos par\u00e1metros de entrada: <code>attr, old, new<\/code>. Vamos a actualizar nuestra fuente de datos en funci\u00f3n del valor del slider. As\u00ed que creamos un nuevo diccionario que corresponder\u00e1 al a\u00f1o del control deslizante y, a partir de esto, actualizamos nuestra trama. Tambi\u00e9n actualizamos el t\u00edtulo en consecuencia.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Make a slider object: slider<br>slider = Slider(start=min(final_df.year), end=max(final_df.year), step=1, value=min(final_df.year), title='Year')<br><br><br>def update_plot(attr, old, new):<br>    # set the `yr` name to `slider.value` and `source.data = new_data`<br>    yr = slider.value<br><br>    new_data = {<br>        'x': final_df.gdp[final_df['year'] == yr],<br>        'y': final_df.co2[final_df['year'] == yr],<br>        'country': final_df.country[final_df['year'] == yr],<br>        'region': final_df.region[final_df['year'] == yr],<br>    }<br>    source.data = new_data<br><br>    # Add title to figure: plot.title.text<br>    plot.title.text = 'Gapminder data for %d' % yr<br><br><br># Attach the callback to the 'value' property of slider<br>slider.on_change('value', update_plot)<\/pre>\n\n\n\n<p>Con esta cantidad de puntos de datos, la trama se desordena muy r\u00e1pidamente. As\u00ed que para agregar m\u00e1s claridad a cada peque\u00f1o c\u00edrculo que se presentar\u00e1 aqu\u00ed, decid\u00ed incluir HoverTool en esta figura.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Create a HoverTool: hover<br>hover = HoverTool(tooltips=[('Country', '@country'), ('GDP', '@x'), ('CO2 emission', '@y')])<br><br># Add the HoverTool to the plot<br>plot.add_tools(hover)<\/pre>\n\n\n\n<p>HoverTool acepta una lista de tuplas con el primer valor como etiqueta y el segundo valor de detalle del origen de datos.<\/p>\n\n\n\n<p>Lo hemos hecho con todos los componentes de nuestra peque\u00f1a aplicaci\u00f3n, solo unas pocas l\u00edneas finales de c\u00f3digo para crear un dise\u00f1o y agregarlo al documento actual.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Make a row layout of widgetbox(slider) and plot and add it to the current document<br>layout = row(widgetbox(slider), plot)<br>curdoc().add_root(layout)<\/pre>\n\n\n\n<p>\u00a1Y hemos terminado! \u00a1Felicidades! Ejecutamos este c\u00f3digo y \u2026 Nada. No hay errores (o tal vez algunos errores, pero luego los arreglas y no hay errores) y no hay aplicaci\u00f3n, y no hay visualizaci\u00f3n O_o. \u00bfPor qu\u00e9 demonios pas\u00e9 todo ese tiempo para crear una trama genial y no obtengo nada? Ni siquiera la explicaci\u00f3n de lo que hice mal?<\/p>\n\n\n\n<p>Ese fue mi primer pensamiento cuando intent\u00e9 ejecutar la aplicaci\u00f3n. Pero luego record\u00e9 un truco en el que primero tienes que iniciar un servidor que ser\u00e1 un servidor para esta visualizaci\u00f3n.<\/p>\n\n\n\n<p>Entonces, lo siguiente y lo \u00faltimo que debe hacer es ejecutar el c\u00f3digo siguiente desde su l\u00ednea de comando:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bokeh serve --show my_python_file.py<\/pre>\n\n\n\n<p>Y  la visualizaci\u00f3n se abrir\u00e1 autom\u00e1ticamente en una nueva pesta\u00f1a del navegador.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"450\" src=\"http:\/\/35.180.88.53\/wp-content\/uploads\/2019\/01\/ezgif.com-video-to-gif.gif\" alt=\"\" class=\"wp-image-750\"\/><\/figure>\n\n\n\n<p>A pesar de ser el m\u00e1s popular, <code>matplotlib<\/code> no es la herramienta de visualizaci\u00f3n de datos m\u00e1s f\u00e1cil de usar y tiene sus propias limitaciones, yyyyyy&#8230; realmente no me gusta. As\u00ed que Bokeh es una soluci\u00f3n posible si perteneces a la misma cohorte de personas que yo. Pru\u00e9balo y d\u00e9jame saber qu\u00e9 piensas.<\/p>\n\n\n\n<p>\u00a1Gracias por tu atenci\u00f3n, espero que esta peque\u00f1a introducci\u00f3n a Bokeh sea \u00fatil y que tengas un gran d\u00eda! (o noche si est\u00e1s leyendo esto antes de ir a la cama: D)<\/p>\n\n\n\n<p>P.S. Tambi\u00e9n quiero probar plotly, he visto muchos comentarios positivos.<\/p>\n\n\n\n<p>P.S.S. C\u00f3digo en <a href=\"https:\/\/github.com\/slehkyi\/notebooks-for-articles\/blob\/master\/co2_world.py\">Github<\/a>.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p style=\"text-align:center\"> Foto de\u00a0<a href=\"https:\/\/unsplash.com\/photos\/e4usjv5lmhE?utm_source=unsplash&#038;utm_medium=referral&#038;utm_content=creditCopyText\">Yosh Ginsu<\/a>\u00a0en\u00a0<a href=\"https:\/\/unsplash.com\/search\/photos\/smoke-landscape?utm_source=unsplash&#038;utm_medium=referral&#038;utm_content=creditCopyText\">Unsplash<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recientemente encontr\u00e9 \u00e9sta biblioteca, aprend\u00ed un poco sobre ella, la prob\u00e9, por supuesto, y decid\u00ed compartir mis pensamientos. Desde el&hellip;<\/p>\n","protected":false},"author":1,"featured_media":752,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"translation":{"provider":"WPGlobus","version":"3.0.0","language":"es","enabled_languages":["gb","es","uk"],"languages":{"gb":{"title":true,"content":true,"excerpt":false},"es":{"title":true,"content":true,"excerpt":false},"uk":{"title":true,"content":true,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/posts\/746"}],"collection":[{"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/comments?post=746"}],"version-history":[{"count":19,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/posts\/746\/revisions"}],"predecessor-version":[{"id":800,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/posts\/746\/revisions\/800"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/media\/752"}],"wp:attachment":[{"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/media?parent=746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/categories?post=746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sergilehkyi.com\/es\/wp-json\/wp\/v2\/tags?post=746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}