%matplotlib inline
Observaciones:
¿Porqué esta presentación?
¿Se pueden hacer encuestas interactivas en presentaciones con jupyter notebooks?
¿Consejos sobre hacer presentaciones en general?
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.
¿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?
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.¿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.
¿Se puede?
Sí, y de varias maneras distintas.
¿Cómo?
IFrames.
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
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.
Podemos usar IFrame con los servicios de alguna compañía especializada en encuestas interactivas:
Probemos este método con una encuesta simple:
from IPython.display import IFrame
IFrame("https://pollev.com/sebastianflo711", width=800, height=600)
Link encuesta:
¿Qué debe cumplir un sitio de encuestas interactivas?
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!
¿Cómo se debe usar?
¿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.
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)
Link encuesta:
¿Qué debe cumplir un sitio de encuestas nivel 2?
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 |
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("");
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.
¿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)
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):
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""")
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 |
Ventaja | Desventaja | |
Complejidad | Simple | |
Precio | Versión gratis es suficiente | |
Gráficos | Configurables | Requieren código |
Datos | Con accceso a datos |
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. |
Encuesta sobre la charla: