<jupyter_start><jupyter_text>MAT281 Aplicaciones de la Matemática en la Ingeniería  Intrucciones- Completa tus datos personales (nombre y rol USM).- Debes enviar este .ipynb con el siguiente formato de nombre: 0X_filename_NOMBRE_APELLIDO.ipynb con tus respuestas a <EMAIL> y <EMAIL> .- Se evaluará:    * Soluciones    * Código    * Al presionar  Kernel -> Restart Kernel and Run All Cells deben ejecutarse todas las celdas sin error.- La escala es de 0 a 4 considerando solo valores enteros.- __La entrega es al final de esta clase.____Nombre:____Rol:__  ¿Qué contenido aprenderemos?* El significado de **Visualización Declarativa*** Una introducción a `Altair`  Visualización DeclarativaA modo de resumen, se refiere a construir visualizaciones a partir de los siguientes elementos:* _Data_* _Transformation_* _Marks_* _Encoding_* _Scale_* _Guides_ Para una visualización declarativa adecuata, los datos deben encontrarse en el formato _*Tidy*_, es decir:* Cada variable corresponde a una columna.* Cada observación corresponde a una fila.* Cada tipo de unidad de observación corresponde a una tabla. Un ejemplo de datos _Tidy_:<jupyter_code>import pandas as pd
df = pd.DataFrame({
                   "ID": range(5),
                   "Color": ["Azul", "Rojo", "Azul", "Azul", "Rojo"],
                   "Duración": [1, 1, 3, 3, 3]
                  })
df.head()<jupyter_output><empty_output><jupyter_text>Un ejemplo de datos __NO__ _Tidy_<jupyter_code>df.pivot(index="ID", columns="Color", values="Duración")<jupyter_output><empty_output><jupyter_text>No es _Tidy_ puesto que la variable "Color" utiliza más de una columna. ![key](http://i.imgur.com/G0dFaFF.png) ![hyp](http://i.imgur.com/JdPmESe.png)  Diferencias entre enfoques| Imperativa  | Declarativa | | ------|------------ | | Especificar _cómo_ se debe hacer algo | Especificar _qué_ se quiere hacer || Especificación y ejecución entrelazadas | Separar especificación de ejecución || _Colocar un círculo rojo aquí y un círculo azul acá_ | _Mapear `x` como posición e `y` como el color_ |La visualización declarativa te deja pensar sobre los datos y sus relaciones, más que en detalles sin importancia.  Ejemplo El _Iris dataset_ es un conjunto de datos famoso por ser un buen ejemplo, por lo que nos servirá para mostrar una de las mayores diferencias entre una visualización imperativa (como `matplotlib`) versus una declarativa (como `altair`).<jupyter_code>import altair as alt
from vega_datasets import data  # Una librería con muchos datasets
# Una breve descripción
data.iris?
iris = data.iris()
iris.head()<jupyter_output><empty_output><jupyter_text>El ejemplo clásico consiste en graficar _sepalWidth_ versus _petalLength_ y colorear por especie.   ImperativoEn `matplotlib` sería algo así:<jupyter_code>import matplotlib.pyplot as plt
color_map = dict(zip(iris["species"].unique(), 
                     ["blue", "green", "red"]))

plt.figure(figsize=(10,6))

for species, group in iris.groupby("species"):
    plt.scatter(group["petalLength"], 
                group["sepalWidth"],
                color=color_map[species],
                alpha=0.3,
                edgecolor=None,
                label=species,
               )
    
plt.legend(frameon=True, title="species")
plt.xlabel("petalLength")
plt.ylabel("sepalWidth")<jupyter_output><empty_output><jupyter_text>DeclarativoEn `altair` sería algo así:<jupyter_code>alt.Chart(iris, background="white").mark_point().encode(
    x="petalLength",
    y="sepalWidth",
    color="species"
)<jupyter_output>/home/alonsolml/miniconda3/envs/mat281_2018S2/lib/python3.6/site-packages/altair/utils/core.py:284: FutureWarning: A future version of pandas will default to `skipna=True`. To silence this warning, pass `skipna=True|False` explicitly.
  attrs['type'] = infer_vegalite_type(data[attrs['field']])<jupyter_text>Spoiler: Solo bastan un par de líneas extras para crear un gráfico interactivo!<jupyter_code>alt.Chart(iris, background="white").mark_point().encode(
    x="petalLength",
    y="sepalWidth",
    color="species",
    tooltip="species"
).interactive()<jupyter_output><empty_output><jupyter_text>AltairAltair is a declarative statistical visualization library for Python, based on Vega and Vega-Lite, and the source is available on GitHub.With Altair, you can spend more time understanding your data and its meaning. Altair’s API is simple, friendly and consistent and built on top of the powerful Vega-Lite visualization grammar. This elegant simplicity produces beautiful and effective visualizations with a minimal amount of code.  DataLos datos en Altair son basados en Dataframe de Pandas, los cuales deben ser _Tidy_ para una mejor experiencia.El objeto _*Chart*_ es el fundamental, pues tiene como argumento los datos.<jupyter_code># Utilizaremos estos datos como ejemplo
import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
import altair as alt
chart = alt.Chart(data)<jupyter_output><empty_output><jupyter_text>Mark¿Cómo queremos que se vean los datos? La respuesta está en los _marks_, que en Altair corresponden a un método de un objeto _Chart_.<jupyter_code>alt.Chart(data).mark_point()<jupyter_output><empty_output><jupyter_text>La representación anterior consiste en un solo punto, pues aún no se ha especificado las posiciones de los puntos.  EncodingCanales asociados a columnas de los datos con tal de separar visualmente los elementos (que para estos datos se están graficando puntos). Por ejemplo, es posible codificar la variable `a` con el canal `x`, que representa el eje horizontal donde se posicionan los puntos. Esto es posible mediante el método `encode` de los objetos _Charts_.<jupyter_code>alt.Chart(data).mark_point().encode(
    x='a',
)<jupyter_output><empty_output><jupyter_text>Los principales canales de _encoding_ son `x`, `y`, `color`, `shape`, `size`, etc. los cuales se pueden designar utilizando el nombre de la columna asociada a los datos. Finalmente, separemos la posición vertical asignando el canal `y`, que como te imaginas, corresponde al eje vertical.<jupyter_code>alt.Chart(data).mark_point().encode(
    x='a',
    y='b'
)<jupyter_output><empty_output><jupyter_text>TransformaciónAltair permite incluso transformar datos con tal de entregar mayor flexibilidad, para ello dispone de una sintaxis incorporada para `Agregaciones`. Por ejemplo, para calcular el promedio.<jupyter_code>alt.Chart(data).mark_point().encode(
    x='a',
    y='average(b)'
)<jupyter_output><empty_output><jupyter_text>Aunque en realidad es más acertado utilizar gráficos de barra para mostrar agregaciones. Es tan fácil como cambiar el método `mark_point()` por `mark_bar()`.<jupyter_code>alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)<jupyter_output><empty_output><jupyter_text>Muchas más personalizacionesPor defecto, Altair a través de Vega-Lite realiza algunas elecciones sobre las propiedades por defecto en cada visualización. Sin embargo, Altair también provee una API para personalizar los gráficos. Por ejemplo, es posible especificar el título de cada eje utilizando los atributos de los canales. Inclusive es posible escoger el color de los _marks_.<jupyter_code>alt.Chart(data).mark_bar(color='firebrick').encode(
    y=alt.Y('a', axis=alt.Axis(title='category')),
    x=alt.X('average(b)', axis=alt.Axis(title='avg(b) by category'))
)<jupyter_output><empty_output><jupyter_text>En el ejemplo anterior no basta con solo el nombre de la columna, es necesario crear el objeto `alt.__` correspondiente a los canales. Otro ejemplo útil consiste en juntar dos gŕaficos en una misma figura.<jupyter_code>vertical_chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)

horizontal_chart = alt.Chart(data).mark_bar(color='firebrick').encode(
    y=alt.Y('a', axis=alt.Axis(title='category')),
    x=alt.X('average(b)', axis=alt.Axis(title='avg(b) by category'))
)

vertical_chart | horizontal_chart<jupyter_output><empty_output><jupyter_text>Inclusive se puden sumar!<jupyter_code>vertical_chart_point = alt.Chart(data).mark_point(color='firebrick').encode(
    x='a',
    y='average(b)'
)

vertical_chart + vertical_chart_point<jupyter_output><empty_output><jupyter_text>Ejemplos  Histogramas múltiples<jupyter_code>import numpy as np
np.random.seed(42)

# Generating Data
df = pd.DataFrame({'Trial A': np.random.normal(0, 0.8, 1000),
                   'Trial B': np.random.normal(-2, 1, 1000),
                   'Trial C': np.random.normal(3, 2, 1000)})

# Tidying Data
df = pd.melt(df, id_vars=df.index.name,
             value_vars=df.columns,
             var_name='Experiment',
             value_name='Measurement')

df.head()
alt.Chart(df).mark_area(
    opacity=0.3,
    interpolate='step'
).encode(
    alt.X('Measurement', bin=alt.Bin(maxbins=100)),
    alt.Y('count()', stack=None),
    alt.Color(
        'Experiment',
        scale=alt.Scale(range=['#0000ff', '#008000', '#ff0000'])
    )
).properties(
    title='Multi-Layer Histogram',
    width=600, 
    height=400 
)<jupyter_output><empty_output><jupyter_text>Gráfico interactivo con _Cross-Highlight_Este ejemplo muestra un gráfico interactivo donde las selecciones en una parte del gráfico afectan lo que se muestra en otros paneles. Al hacer click en el gráfico de barras se observa como se adapta el gráfico superior.<jupyter_code>from vega_datasets import data
pts = alt.selection(type="single", encodings=['x'])

rect = alt.Chart(data.movies.url).mark_rect().encode(
    alt.X('IMDB_Rating:Q', bin=True),
    alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
    alt.Color('count()',
        scale=alt.Scale(scheme='greenblue'),
        legend=alt.Legend(title='Total Records')
    )
)

circ = rect.mark_point().encode(
    alt.ColorValue('grey'),
    alt.Size('count()',
        legend=alt.Legend(title='Records in Selection')
    )
).transform_filter(
    pts
)

bar = alt.Chart(data.movies.url).mark_bar().encode(
    x='Major_Genre:N',
    y='count()',
    color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
).properties(
    selection=pts,
    width=550,
    height=200
)

alt.vconcat(
    rect + circ,
    bar
).resolve_legend(
    color="independent",
    size="independent"
)<jupyter_output><empty_output><jupyter_text>_Tooltip_ multilíneaEste ejemplo muestra cómo es posible utilizar selecciones y capas para crear un comportamiento similar un _tooltip_ vinculado a la posición x del cursor. A continuación se emplea un pequeño truco para aislar la posición x del cursor: agregamos algunos puntos transparentes con solo una codificación `x` (sin codificación `y`) y vinculamos una selección más cercana a estos, vinculada al campo `x`.<jupyter_code>np.random.seed(42)
df = pd.DataFrame(np.cumsum(np.random.randn(100, 3), 0).round(2),
                    columns=['A', 'B', 'C'], index=pd.RangeIndex(100, name='x'))
df = df.reset_index().melt('x', var_name='category', value_name='y')

# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
                        fields=['x'], empty='none')

# The basic line
line = alt.Chart().mark_line(interpolate='basis').encode(
    x='x:Q',
    y='y:Q',
    color='category:N'
)

# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart().mark_point().encode(
    x='x:Q',
    opacity=alt.value(0),
).add_selection(
    nearest
)

# Draw points on the line, and highlight based on selection
points = line.mark_point().encode(
    opacity=alt.condition(nearest, alt.value(1), alt.value(0))
)

# Draw text labels near the points, and highlight based on selection
text = line.mark_text(align='left', dx=5, dy=-5).encode(
    text=alt.condition(nearest, 'y:Q', alt.value(' '))
)

# Draw a rule at the location of the selection
rules = alt.Chart().mark_rule(color='gray').encode(
    x='x:Q',
).transform_filter(
    nearest
)

# Put the five layers into a chart and bind the data
alt.layer(line, selectors, points, rules, text,
          data=df, width=600, height=300)<jupyter_output><empty_output><jupyter_text>EjerciciosUtilizaremos el conjunto de datos de películas que se encuentra en `vega_datasets` debido a la gran cantidad de variables que posee.<jupyter_code># data.movies?
from datetime import timedelta

movies = (data.movies()
    .assign(release_date_fix=lambda df: pd.to_datetime(df["Release_Date"]).apply(lambda x: x - timedelta(365.25 * 100) if x.year >= 2020 else x))
)
movies.head()
movies.describe(include="all")<jupyter_output><empty_output><jupyter_text>Ejercicio 1 [1 pt]Crear un gráfico de líneas, donde el eje X corresponda al año y el eye Y al promedio de la calificación de IMDB.<jupyter_code>alt.Chart(movies).mark_FIX_ME_PLEASE().encode(
    x=alt.X('release_date_fix:T', 
        timeUnit='year',
        axis=alt.Axis(title='Año'),
           ),
    y=# FIX ME PLEASE
)<jupyter_output><empty_output><jupyter_text>Ejercicio 2 [1 pt]Escoge tres género de películas y crea un gráfico de líneas, donde cada curva corresponda a un género (`Major_Genre`). el eje X corresponda al año y el eye Y al promedio de la calificación de IMDB. Tip: Puedes crear un dataframe filtrado y entregarlo como argumento a `alt.Chart` o puedes utilizar [Field Predicates](https://altair-viz.github.io/user_guide/transform.html?highlight=moviesfield-predicates).<jupyter_code>alt.Chart().mark_FIX_ME_PLEASE.encode(
    # FIX ME PLEASE
)<jupyter_output><empty_output><jupyter_text>Ejercicio 3 [2 pts]El siguiente gráfico es un poco más elaborado por lo que a continuación se enumera todas las características que debe poseer:* _Scattet Plot_, con círculos de tamaño 60 y opacidad 0.5.* Eje horizontal puntuación de _Rotten Tomatoes_.* Eje vercital el presupuesto de producción.* Color según _Creative Type_.* Debe ser interactivo y tener como _tooltip_ el título y director de la película.* Agregar las siguientes propiedades:     - Título (el que estimes conveniente)    - Ancho: 600    - Alto: 400<jupyter_code>alt.Chart(movies).mark_FIX_ME_PLEASE(FIX).encode(
    x= # FIX ME PLEASE
    y= # FIX ME PLEASE
    color= # FIX ME PLEASE
    tooltip= # FIX ME PLEASE
).properties(
   # FIX ME PLEASE
).interactive()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11134395082425258, 'fraction_numerical': 0.00998882369376921, 'mean_word_length': 4.688120778704807, 'pattern_counts': {'":': 3, '<': 90, '<?xml version=': 0, '>': 92, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '22', 'dir': 'jupyter-structured-clean-dedup', 'id': '586798', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 4961, 'n_tokens_neox': 4816, 'n_words': 1385, 'path': 'm03_visualizacion/03_visualizacion_declarativa/03_visualizacion_declarativa.ipynb', 'repo_name': 'sebastiandres/mat281_2018S2', 'size': '14348'}