Sesión 6
Jesús Fernández (fernandez.cuesta@gmail.com)
10 Abril 2019
Representamos datos de forma gráfica porque:
Realizar gráficas desde un lenguaje de programación:
En general, seguiremos un procedimiento:
matplotlib (plugin)Desde un terminal (Anaconda Prompt o terminal de VSCODE):
> jupyter notebook☝ Fragmentos de código encerrados entre ‘
#####’
pyplot: módulo con interfaz parecida a MATLABPara importar pyplot:
Partes de una figura

Los componentes más importantes son:
Como regla general seguiremos los siguientes pasos:
Nota: 1 y 2 se pueden combinar en un mismo comando
De forma simplificada, los ejes y la figura se crean simultáneamente:
En jupyter/ipython, los gráficos aparecerán automáticamente si la primera línea es:
De lo contrario necesitaremos ejecutar:
… para mostrar cada gráfico
np.array)pandas.DataFrameEl tipo de datos nativo es np.array.
⚠ El resto puede requerir sanear/homogeneizar los datos ⚠
Para crear una tupla (figura, ejes) usaremos:
plt.subplots()
n, m): crea una figura con varias zonas de dibujo distribuidas en n filas y m columnasplt.subplot()¡Ojo!:
plt.subplot()!=plt.subplots()
nrows, ncols, index): crea un ejepyplot está (parcialmente) integrado en pandasAxes” sobre el que poder trabajar
# Crea la figura y los ejes
fig, ax = plt.subplots()
# siempre se devuelve referencia al eje
ax2 = df.plot.scatter(
'a', 'b', c='c', s=df['d'],
colormap='viridis', alpha=.5,
title='Scatter con pandas', rot='vertical',
ax = ax;
)
ax.annotate(
'Defecto', xy=(1.9, -17),
xytext=(2, -20),
arrowprops=dict(facecolor='black', shrink=0.05)
)
ax2 == ax # dos referencias al mismo objeto
True
Sintaxis

Usar pandas es conveniente y mucho más sencillo:
provincias = ['Cantabria', 'Madrid', 'Murcia', 'León', 'Albacete']
index = np.arange(len(provincias)) + 0.3
y_offset = np.zeros(len(marriages.Total.columns))
cell_text = []
for row in marriages.Total.columns:
_data = marriages.Total.loc[provincias, row]
plt.bar(index, _data, bottom=y_offset, width=0.5)
y_offset = y_offset + _data
cell_text.append(["%1.1f" % (x / 1000.0) for x in y_offset])
cell_text.reverse()
tabla = plt.table(cellText=cell_text,
rowLabels=marriages.Total.columns,
colLabels=provincias,
loc='bottom')
plt.legend(marriages.Total.columns)
plt.title('Total Matrimonios en 2017')con pandas, lo equivalente sería:

pandas.DataFrame.plot().matplotlib sobre el objecto “Axes”:pandasscatter)df.plot.scatter(
x='a', y='b', # nombres de las columnas del dataframe
c='c', # columna con datos de color
s=df['d'], # tamaño de los puntos
colormap='viridis', # paleta de color
alpha=.5, # transparencia
title='Scatter con pandas', # título
rot='vertical', # rotar etiquetas del eje 'x'
)

DataFrame tiene propiedades de “índice temporal” (DateTimeIndex)
:::
np.random.seed(0)
N = 5
data = pd.DataFrame(
{'Grupo A': np.random.randint(1, 20, N),
'Grupo B': np.random.randint(1, 20, N),
'Grupo C': np.random.randint(1, 20, N)},
index=range(1, N+1)
)
ax = plt.subplot(1, 2, 1)
data.plot.area(
stacked=False,
alpha=.6,
title='Gráfico de área',
ax=ax)
ax = plt.subplot(1, 2, 2)
data.plot.area(
title='Gráfico de área (apilado)',
ax=ax)
pie chart)pandaspd.DataFrame.plot()Es posible pasar argumentos para realizar personalizaciones rápidas.
matplotlib, bien como argumentos adicionales o sobre los ejes
NaN)df.fillna()
df.interpolate()
jupyter notebookax: ejes sobre los que dibujar
1.2. Barras apiladas (stacked)

subplots [True|False]: subplot para cada columna dibujada
layout: (n_filas, n_columnas), opcional con subplot=True
2.2. layout como parámetro de plt.subplots()

sharex/sharey: compartir ejes (subplots)
title:
str: título de la figuralist(str): título de cada subplot
figsize: tamaño de la figura
stacked [True|False]: apilar datos
grid [True|False]: dibujar cuadrícula
rot: 'horizontal', 'vertical', o número (en grados)
xlim, ylim: tuplas (lo, hi) para delimitar visualización
colormap: mapa de colores (plt.colormaps())
secondary_y: segundo eje de ordenadas
table [True|False]: mostrar tabla bajo el gráfico
pyplotpyplotjupyter notebookEl color de línea para un gráfico individual se puede controlar mediante una cadena de texto que defina color+estilo+marcador (p.e. 'r--'), en cualquier orden, todos opcionales:
colors = {'b': 'blue', 'g': 'green', 'r': 'red', 'c': 'cyan', 'm': 'magenta',
'y': 'yellow', 'k': 'black', 'w': 'white'}
lineStyles = {'-': '_draw_solid', '--': '_draw_dashed', '-.': '_draw_dash_dot',
':': '_draw_dotted', 'None': '_draw_nothing',
' ': '_draw_nothing', '': '_draw_nothing'}
markers = {
'.': 'point', ',': 'pixel', 'o': 'circle', 'v': 'triangle_down',
'^': 'triangle_up', '<': 'triangle_left', '>': 'triangle_right',
'1': 'tri_down', '2': 'tri_up', '3': 'tri_left', '4': 'tri_right',
'8': 'octagon', 's': 'square', 'p': 'pentagon', '*': 'star',
'h': 'hexagon1', 'H': 'hexagon2', '+': 'plus', 'x': 'x', 'D': 'diamond',
'd': 'thin_diamond', '|': 'vline', '_': 'hline', 'P': 'plus_filled',
'X': 'x_filled', 0: 'tickleft', 1: 'tickright', 2: 'tickup', 3: 'tickdown',
4: 'caretleft', 5: 'caretright', 6: 'caretup', 7: 'caretdown',
8: 'caretleftbase', 9: 'caretrightbase', 10: 'caretupbase',
11: 'caretdownbase', 'None': 'nothing', None: 'nothing', ' ': 'nothing',
'': 'nothing'
}Color/estilo de línea
xticks/yticks

Títulos, etiquetas y anotaciones

Título de la figura --------->
Título del subplot (Axes) --->
Título de cada eje (Axis) --->
Anotaciones ----------------->
Leyenda
(line1, ) = ax.plot([1.5, 2, 3],
label='IPC')
(line2, ) = ax.plot([1, 1.2, 1.3],
label='Salarios')
ax.legend(loc='upper left')loc: define dónde emplazar la leyenda
best, upper right, upper left, lower left, lower right, right, center left, center right, lower center, upper center, center

:::
matplotlib.rcParams
Podemos cambiar a estilos preconfigurados:
y/o modificar parámetros (plt.rcParams) individualmente
salvo cambio temporal de estilos:

seaborn
:::
pyplotmatplotlib/pyplot.plot())N = 75
np.random.seed(45987230)
fig, (ax1, ax2) = plt.subplots(2, 1,
figsize=(7, 10))
a = np.random.randint(low=1, high=11, size=50)
b = a + np.random.randint(1, 5, size=a.size)
x = np.linspace(0, 1, N)
y = np.random.gamma(5, size=N)
colors = np.random.rand(N)
#####
ax1.scatter(x=a, y=b, marker='o', c='r',
edgecolor='b')
ax2.scatter(
x, y, # x=x, y=y
s=np.random.randint(10,800, N), # tamaño
marker='v', # tipo de marcador
c=colors, # colores
alpha=0.4 # nivel de transparencia
)
#####
ax1.set_title('$a$ vs $b$')
ax2.set_title('$x$ vs $y$')
fig.suptitle("Scatterplot")
Gráfico de barras (barplot)
ax1.bar(
ind, # eje de abcisas
men_std, # eje de ordenadas
width, # grosor de barra
color='#0055ff' # color de barra (RGB)
)
ax1.bar(
ind,
women_std,
width,
color='#fabada',
bottom=men_std # apilado
)
# Barras horizontales
ax2.barh( # cambia orden (y, x)
ind, # eje 'y' !
men_means, # eje 'x' !
width, # grosor de barra
color='#0055ff' # color (RGB)
)
ax2.barh( # cambia orden (y, x)
ind, # eje 'y' !
women_means, # eje 'x' !
width, # grosor de barra
color='#fabada' # color (RGB)
)
Histograma
fig, ax = plt.subplots(2, figsize=(10,5))
bins = 20
x1 = np.random.gamma(10, size=1000)
x2 = np.random.randn(1000)
ax1, ax2 = ax.flatten()
#####
(ax1_values, _, _) = ax1.hist(x1, bins=bins, facecolor='brown', alpha=.7);
(_, ax2_bins, _) = ax2.hist(x2, alpha=.7, cumulative=True,
log=True, orientation='horizontal')
#####
Diagrama circular (pie)

Guardar figura a fichero (de forma programática)
from sklearn.datasets import load_iris
iris = load_iris()
plt.style.use('ggplot')
fig, ax = plt.subplots(figsize=(7, 6))
formatter = plt.FuncFormatter(lambda i, *args: iris.target_names[int(i)])
plt.scatter(iris.data[:, 0], iris.data[:, 1], c=iris.target)
plt.colorbar(ticks=[0, 1, 2], format=formatter)
#####
fig.savefig('iris.pdf')
#####Tipos de fichero soportados, según backend:
jupyter notebookCapa de abstracción que simplifica ciertas tareas enfocadas a análisis estadístico
Con matplotlib: …
from scipy.stats import gaussian_kde
ax1 = plt.subplot2grid((4, 4), (1, 0), colspan=3, rowspan=3)
ax2 = plt.subplot2grid((4, 4), (0, 0), colspan=3)
ax3 = plt.subplot2grid((4, 4), (1, 3), rowspan=3)
crashes.plot.kde(y='speeding', ax=ax2, sharex=ax1, legend=None)
crashes.plot.hist(y='speeding', bins=6, ax=ax2, sharex=ax1, normed=True,
legend=None, alpha=.5, color='red')
crashes.plot.scatter(x='speeding', y='alcohol', ax=ax1, color='red', s=50)
ax2.set_ylabel('')
ax2.set_yticks=[]
ax2.set_yticklabels=[]
# No está soportado directamente el rotado en kde
kde_speeding = gaussian_kde(crashes.alcohol)
y = np.linspace(np.amin(crashes.alcohol), np.amax(crashes.alcohol), 100)
ax3.plot(kde_speeding(y), y)
crashes.plot.hist(y='alcohol', ax=ax3, sharey=ax1, normed=True, legend=None,
orientation='horizontal', alpha=.5, color='red')Multitud de gráficas pre-establecidas


jupyter

jupyterjupyter