#!/usr/bin/env python3
from traitlets.config.manager import BaseJSONConfigManager
from pathlib import Path
path = Path.home() / ".jupyter" / "nbconfig"
cm = BaseJSONConfigManager(config_dir=str(path))
cm.update(
"rise",
{
"theme": "sky",
"transition": "none",
}
)
%matplotlib inline
Observaciones:
Hola. Mi nombre es Sebastián Flores, y quiero compartir algunos experimentos que realicé para realizar encuestas en vivo mientras se presenta en jupyter notebook con la extensión RISE. No es necesario que tomen apuntes, la presentación y todos los enlaces están en mi github: sebastiandres (el repo se llama charlas, es el primero).
¿Porqué esta presentación?
La necesidad nació hace algunos meses cuando la noche anterior a realizar una charla a unos estudiantes, quise realizar una encuesta en vivo, pero me di cuenta que no sabía como hacerlo sin salir de RISE y jupyter notebook. Mi talento googleador tampoco me ayudó, así que supongo que si alguien ya lo ha hecho, no lo ha documentado. Así que al menos esto sirve para auto-contestarme. Esto va para ti, Sebastian del lejano pasado.
La presentación está estructurada de lo más general a lo más específico, y de lo más mainstream a lo más geek/hipster. Así que un poco de paciencia si hay cosas que parecen muy evidentes.
¿Consejos sobre hacer presentaciones en general?
Relato: ¿Cómo hacer una buena presentación? Este es un tema en sí mismo. No soy para nada un experto, pero he aprendido algunas cosas. Relato: Aunque parezca un consejotrivial, hay 2 elementos a considerar: saber quién es la audiencia y preparar el contenido necesario. Y haber ensayado varias veces la presentación y ser familiar con el contenido es la mejor forma de que el relato sea fluido. Al final, toda habilidad es como un músculo. Cuando lo ejercitas, se vuelve más fuerte y resulta más fácil usarlo. Esta misma presentación ya la he ensayado unas 10 veces. Sí, toma tiempo.
Si forma parte importante de tu día a día, investiga y aprende a hacer mejores presentaciones.
Libro que considero muy bueno: Confessions of a public speaker - Scott Berkum.
Relato: Por supuesto, hay varios libros que se pueden leer al respecto. A mi me gustó este. Confessions of a public Speaker - Scott Berkum. Consejos prácticos y con un tono de humor.
¿jupyter notebook? ¿RISE?
¿Qué es la extensión RISE?
Una celda de jupyter notebook se puede clasificar (adicionalmente al code/markdown) como:
Toda la info en https://rise.readthedocs.io/
¿Qué es la extensión RISE?
Relato: Si les interesa pueden buscar un tutorial más completo sobre hacer presentaciones en RISE. Pero en resumen, es lo que muestra esta animación (gif). Basta marcar una celda de jupyter notebook con la propiedad “slide”, “sub-slide”, “fragment”, o “” para que esta adquiera la propiedad. Y luego se pone en modo presentación. ¡Voilá!
Ok, pero... ¿porqué? ¿Porqué? ¿PORQUÉ?
Sí, incluso ejecutar código en python
x = 200
y = 200
x is y
True
a = 300
b = 300
a is b
False
def cheeseburger(n):
return ["bread"] + ["meat", "cheese"]*n + ["bread"]
cheeseburger(3)
['bread', 'meat', 'cheese', 'meat', 'cheese', 'meat', 'cheese', 'bread']
¿Que he aprendido?
git
es tu amigo.Relato: ¿Qué cosas he aprendido en estos años haciendo presentaciones con RISE? (0) Más que jugar con los fonts, regular con Ctrl+ y Ctr- como se ve en pantalla. (1) No tener temor en pedir ideas a la audiencia sobre que valores probar o alternativas de código a implementar. (2) Usar un teclado y mouse inalámbrico, para clases de computación. (3) Poner soluciones pre-definidas a los problemas, en lugar de escribirlos en directo (por tiempo). (4) Saber que textos mostrar y cuales ocultar. (5) Usar un repo para volver a versiones anteriores. Usar un diagrama de celdas y mostrar lo que hace “con algunas cajitas”.
¿Qué queremos?
Realizar encuesta interactiva sin salir del modo presentación (en RISE).
¿Porqué?
Hacer encuestas para obtener retroalimentación de la audiencia cuando importa, sin cambiar pantalla o sistema.
Relato: Bueno, llevamos 5 minutos y todavía no hablamos siquiera del problema ¡ni código!. ¿Qué es lo que intentamos resolver? Cuando uno realiza presentación a una audiencia desafiante - estudiantes de primer año de universidad, que no resisten 45 minutos sin mirar su celular - resulta interesante proporcionar un medio para obtener retroalimentación de manera sencilla y directa. Pero ¿Podemos hacer eso en presentaciones con jupyter notebook?
¿Se puede?
Sí, y de varias maneras distintas.
¿Cómo?
IFrames.
Relato: Pensaba que era algo muy dificil. Pero finalmente encontré varias formas distintas.
Nuestro héroe se llama IFrame.
from IPython.display import IFrame
IFrame("https://es.wikipedia.org/wiki/Iframe", width=1000, height=500) #https://es.wikipedia.org/wiki/Iframe
Relato: Las funciones HTML y Iframe son nuestras héroes. Todo esfuerzo de lo que haremos recae en sus hombros. Diferencias de html y iframe. DEFINICION DE IFRAME. Mostrar
Más ejemplos ...
from IPython.display import IFrame
IFrame("https://www.python.org/", width=800, height=300)
No siempre funciona:
En general a los sitios (sobre todo los que requieren autentificación y desean hacer tracking de usuarios) bloquean los IFrames.
Más ejemplos ... ¡IFrame nos permite incluso embeber un jupyter notebook dentro de otro!
from IPython.display import IFrame
link="http://localhost:8888/notebooks/2020_02_XX_pycon_rise_and_poll/2020_pycon_RISE_and_poll.ipynb"
#IFrame(link, width=800, height=300) #google, facebook, twitter
Relato: Un aprendizaje interesante que pueden llevarse hoy, es que existen sitios que no permiten ser embebidos en un iframe. Por ejemplo, si tratamos de hacer un iframe de google, nos da el siguiente error. ¿Porqué? Porque XYZ.
Sin embargo, podemos usar un acortador de dirección para evitar ese problema. Por ejemplo, el mismo acordador de dirección de google nos permite bypasear su propia seguridad. Hermoso.
Podemos usar IFrame con los servicios de alguna compañía especializada en encuestas interactivas:
Relato: Solución nivel 1. Meme de “cerebro”. Hay un principio elemental en programación: KISS. Keep it Simple, Stupid. No hay para que reinventar la rueda cuando podemos aprovechar lo que otras personas ya han hecho.
Relato: Hay varias empresas que proporcionan servicios para realizar encuestas en vivo, que funciona a través de páginas web. Algunas de las empresas que pueden revisar para esto son: Mentimeter, Survey, Polleverywhere, por ejemplo. Spoiler Alert: Son todas bastante parecidas.
Probemos este método con una encuesta simple:
from IPython.display import IFrame
IFrame("https://pollev.com/sebastianflo711", width=800, height=600)
Relato: Hagamos un primer experimento. Yo ya cree una encuesta que deberán responder. ¿Listos? En sus celulares, busquen la página web que se encuentra en pantalla y voten. Mostrar con un iframe y leer.
Link encuesta:
¿Qué debe cumplir un sitio de encuestas interactivas?
Relato: ¿Qué necesitamos de esta encuesta? Que tenga las siguientes características: Encuesta accesible con una url pública, para poder compartir el enlace durante la presentación. Gráficos disponibles a partir de una url pública o privada, para incrustarla el grafico en la ppt.
Veamos los resultados de la encuesta anterior.
from IPython.display import IFrame
IFrame("https://www.polleverywhere.com/multiple_choice_polls/7Xwy472JbCrk3fITm12XM", width=800, height=600)
# Observación: ¡requiere estar autentificado como dueño de la encuesta!
Relato: Mientras ustedes votan, podemos ya comenzar a ver los resultados. Ejecutar el iframe varias veces.
¿Cómo se debe usar?
Relato: En general, la versión “gratis” permite hacer preguntas y ver los resultados, pero requiere haberla preparado antes para tener el enlace, y no permite descargar los resultados para explorarlos más “cientificamente”. Es necesario haber creado la presentación de antemano y es más difícil cambiarla a último momento. Dependiendo de la empresa, funciona más o menos fácil y “auto-refresh”.
¿Que viene antes, el huevo o la gallina?
# Solución al problema
# python3 permite usar unicode
sorted(['\N{EGG}', '\N{CHICKEN}'])
['🐔', '🥚']
Solución Nivel 2
Una segunda opción que requiere un poco más de configuración pero entrega más control, es usar un servicio de encuestas tradicional:
Se diferencia que nosotros podemos hacer los gráficos porque podemos descargar los datos.
Relato: El siguiente nivel es enviar una encuesta de un servicio más estándar, como Google Survey, Microsoft Forms, Survey Monkey o Typeform.
Probemos este método con otra encuesta simple:
long_url = "https://forms.office.com/Pages/ResponsePage.aspx?id=zu7OdUTRPU-clJ5rQCX8_4qs5cX1Y7dFhVdiCz848sBUNFU3UzU3OTNHVDhWNURSMEs2WDBUMDdCTi4u"
short_url = "https://bit.ly/2uYDdhm"
iframe_options = {"width":800, "height":600}
IFrame(short_url, **iframe_options)
Notas: Por ejemplo, accedan a la encuesta que se encuentra en la siguiente dirección:
Link encuesta:
Notas: ¿Que fue lo que hicimos acá? Veamos un poco más de detalle. La página web que accesaron tuvo que ser creada antes, y el link para compartir incrustado en la presentación. La tabla con los resultados se interpreta con alguna función apropiada, por ejemplo, en este caso, usé pandas y matplotlib porque porqué no.
long_url = "https://forms.office.com/Pages/AnalysisPage.aspx?id=zu7OdUTRPU-clJ5rQCX8_4qs5cX1Y7dFhVdiCz848sBUNFU3UzU3OTNHVDhWNURSMEs2WDBUMDdCTi4u&AnalyzerToken=ND54U8Erls95gHxjbyWus4LzH6FPyZ35"
short_url = "https://bit.ly/37We2dE"
iframe_options = {"width":800, "height":600}
IFrame(short_url, **iframe_options)
# Alternative to ls data/*.xlsx
import glob
glob.glob("data/*.xlsx")
['data/2020_02_08_encuesta2_pycon.xlsx']
import pandas as pd
df_dict = pd.read_excel("data/2020_02_08_encuesta2_pycon.xlsx", sheet_name=None)
df_dict.keys()
odict_keys(['Hoja1', '_56F9DC9755BA473782653E2940F9', 'Form1'])
df = df_dict["Form1"]
question = df.columns[-1]
print(question)
Which one is the best pet?
df.head()
ID | Start time | Completion time | Name | Which one is the best pet? | ||
---|---|---|---|---|---|---|
0 | 9 | 2020-02-03 14:28:15 | 2020-02-03 14:28:27 | anonymous | NaN | Python |
1 | 10 | 2020-02-08 00:32:22 | 2020-02-08 00:32:27 | anonymous | NaN | Python |
2 | 11 | 2020-02-08 18:00:03 | 2020-02-08 18:00:08 | anonymous | NaN | Cat |
3 | 12 | 2020-02-08 18:00:04 | 2020-02-08 18:00:09 | anonymous | NaN | Cat |
4 | 13 | 2020-02-08 18:00:07 | 2020-02-08 18:00:12 | anonymous | NaN | Cat |
La tabla con los resultados se interpreta con alguna función apropiada, por ejemplo, en este caso, usé pandas y matplotlib porque porqué no.
question_df = df[question]
answer_counts = question_df.value_counts()
answer_counts
Cat 9 Python 7 Dog 3 León 1 Pandas 1 RISE 1 Name: Which one is the best pet?, dtype: int64
from matplotlib import pyplot as plt
answer_counts.plot.barh(figsize=(16,6))
plt.show()
Hagamos un gráfico un poco mejor.
from matplotlib import pyplot as plt
answer_counts.plot.barh(figsize=(16,6), fontsize=16, alpha=0.60)
plt.suptitle(question, fontsize=16)
plt.xlabel("Número de respuestas", fontsize=16)
plt.ylabel("");
Leer.
Solución Nivel 3
La solución más compleja es por supuesto hacer el sistema completo:
En este caso: mysql, flask, flask-mysql y pandas, con algo de html y css, y una librería de javascript para graficar.
Notas: Por supuesto, la versión que nos da más control de todo es hacerlo a lo macgiver. Par los millenials de la sala, macgiver es un programa de televisión donde el protagonista podía hacer una bomba con un moco. En fin, la idea es hacer todo desde cero: la página web con su base de datos y gráficos.
¿Porqué alguien voluntariamente se sometería a este tormento?
Filosofía xkcd:
¿Porqué hacer algo simple cuando podrías hacer algo extremadamente complejo de la manera más simple posible, aprendiendo mucho en el camino?
¿xkcd en python?
import antigravity
from IPython.display import IFrame
IFrame("http://localhost:5000/", width=1200, height=800)
Notas: Sí, es bastante trabajo. Este es un diagrama reducido de cómo funcionaría.
El código de polite se encuentra en https://github.com/sebastiandres/surveys_with_flask_and_xkcd_charts.
Hace uso de muchos recursos públicamente disponibles (además de mysql y python+librerías):
Notas: Pero tiene la ventaja que es posible dejarlo tal y cual lo queremos. Por ejemplo, si quiero cambiar la pregunta y sus opciones durante la presentación. Para lograr esto le di la funcionalidad de que genere automáticamente una encuesta a partir de un texto con formato markdown.
Una de las cosas que más me llamó la atención fue cómo hacer una función que pudiese transformar un texto markdown en la serie de preguntas y opciones de respuesta.
Requería definir convenciones:
:
*
^
Otra opción podría haber sido -
y +
.
Es una mala opción usar o
y m
.
def markdown_parser(my_text):
if my_text.count(":")!=1:
print("Cannot parse, there's an error in the format")
return {"is_format_ok":False, "markdown_str":my_text}
single_option = 0
multiple_option = 0
if ("* " in my_text):
single_option = 1
split_char = "*"
if ("^ " in my_text):
multiple_option = 1
split_char = "^"
# If both False or both True, simultaneoulsy, there's an error
if single_option==multiple_option:
print("Cannot parse, there's an error in the format")
return {"is_format_ok":False, "markdown_str":my_text}
question_str, answer_str = my_text.split(":")
question = question_str.strip()
answer_list = [_.strip() for _ in answer_str.split(split_char)[1:6]] # Skip the empty string, reach to the fifth existing one
answer_list = answer_list + ["" for _ in range(5-len(answer_list))] # Fill with empty ones if needed
question_type = single_option*"radio"+multiple_option*"checkbox" # This is the html convention
# Create the dict
md_dict = {}
md_dict["is_format_ok"] = True
md_dict["markdown_str"] = my_text
md_dict["type_str"] = question_type
md_dict["question_str"] = question
md_dict["option_1_str"] = answer_list[0]
md_dict["option_2_str"] = answer_list[1]
md_dict["option_3_str"] = answer_list[2]
md_dict["option_4_str"] = answer_list[3]
md_dict["option_5_str"] = answer_list[4]
return md_dict
markdown_parser("Q: ^ A * B * C * D * E * F * G ")
Cannot parse, there's an error in the format
{'is_format_ok': False, 'markdown_str': 'Q: ^ A * B * C * D * E * F * G '}
markdown_parser("""Q: ^ A ^ B ^ C ^ D ^ E ^ F ^ G ^ H""")
Hagamos la prueba:
from IPython.display import IFrame
IFrame("http://localhost:5000/survey", width=1000, height=1000)
Veamos los resultados:
from IPython.display import IFrame
IFrame("http://localhost:5000/bar_chart", width=1000, height=1000)
Notas: Para eso, tuve que yo mismo definir ciertas convenciones. Una pregunta de alternativas únicas tipo button, se genera con opciones dadas con *. Una pregunta de alternativas multiples, se genera con alternativas encabezadas por ^.
Notas: Hagamos un último experimento. Respondan a la siguiente encuesta. Ejecutar funcionalidad que permite compilar y mostrar una pregunta. DEBE: Generar una url + decir tipo de pregunta + mostrar html compilado con preguntas a responder.
Notas: Y ahora veamos los resultados. Ejecutar función específica para ver los resultados de la encuesta. Los gráficos, en caso que se pregunten, están hechos con la librería xkcdcharts de javascript que emulan los clásicos dibujos del webcomic xkcd.
Ventaja | Desventaja | |
Complejidad | Trivial | - |
Precio | Versión limitada gratis | Versión pagada con más funcionalidades |
Gráficos | Gráficos predefinidos | Gráficos predefinidos |
Datos | - | Sin accceso a datos |
Notas: Para concluir, veamos los pros y contras de estas 3 opciones. La opción “iframe de empresa de encuestas interactiva” tiene como ventaja el ser extremadamente sencillo, pero con limitaciones en la representación gráfica y en la descarga de resultados, y hay que preparar preguntas de antemano. Pero en relación al tiempo-calidad, es muy conveniente. Imagen: Nobody aint time 4 that
Ventaja | Desventaja | |
Complejidad | Simple | |
Precio | Versión gratis es suficiente | |
Gráficos | Configurables | Requieren código |
Datos | Con accceso a datos |
Notas: La opción “encuesta tradicional” tiene la ventaja de permitir almacenar y revisar los resultados, pero requiere haber creado previamente funciones para descargar y graficar los resultados. Sigue siendo conveniente, pero a veces tiene un delay que hace que los resultados no sean “realmente en vivo”. Hay que preparar preguntas de antemano, y las funciones para graficar. (¿Alguna imagen donde el lag sea divertido?)
Ventaja | Desventaja | |
Complejidad | Bastante complejo. Toma tiempo. Deployment puede ser complejo. | |
Precio | Hosting gratis es suficiente | Time=Money? |
Gráficos | Configurables | Hay que configurarlos completamente. |
Datos | Con accceso completo a datos | Hay que almacenar los datos. |
Notas: La opción “lo haré yo mismo” (imagen de bender con su meme de blackjack y putas) tiene la ventaja de tener todo lo imaginable: control de los datos, control de los gráficos, incluso generación “dinámica” a partir de un markdown. Pero tiene la desventaja de haber necesitado crear todo eso. Pero es un aprendizaje altamente educativo, aunque costoso en tiempo. Si les interesa, pueden ver el repo en mi github: sebastiandres + little_survey_website.
Encuesta sobre la charla:
Slide: ¿Preguntas? Notas: Y bueno, así llegamos a la sección final de preguntas en la cual pasaremos 5 minutos incómodos en silencio, a menos que alguien quiera hacer alguna pregunta y observación. Mientras tanto, pueden responder a una última encuesta: PONER LINK PERO NO MOSTRAR CONTENIDO.