Categorías
Python

Cómo escribir comentarios en Python

 

Tabla de Contenidos

  • histogramas en
  • Python puro

  • , construyendo desde la base: Cálculos de histograma en NumPy
  • Visualizando histogramas con Matplotlib y pandas
  • Trazado de un kernel Densidad Estimación (KDE)
  • una fantasía alternativa con Seaborn
  • otras herramientas de pandas
  • Muy bien, así que debería usar?

Mira ahora Este tutorial tiene un vídeo relacionado curso creado por el equipo del Real Python. Mira que junto con el tutorial escrito para profundizar su comprensión: Python histograma Trazado: NumPy, Matplotlib, pandas y Seaborn

En este tutorial, estará equipado para hacer la producción de calidad, listas para presentar histogramas Python con una gama de opciones y características.

Si tiene introductoria al conocimiento intermedio en Python y estadísticas, puede utilizar este artículo como una ventanilla única para la construcción y el trazado de histogramas en Python usando bibliotecas de su pila científica, incluyendo NumPy, Matplotlib, pandas, y Seaborn.

Un histograma es una gran herramienta para evaluar rápidamente una distribución de probabilidad que se entiende intuitivamente por casi cualquier público. Python ofrece un puñado de opciones diferentes para la construcción y el trazado de histogramas. La mayoría de la gente sabe un histograma mediante su representación gráfica, que es similar a un gráfico de barras:

Este artículo le guiará a través de la creación de parcelas como la de arriba como los así como más complejos. Esto es lo que va a cubrir:

  • Edificio histogramas en Python puro, sin el uso de bibliotecas de terceros
  • La construcción de histogramas con NumPy para resumir los datos subyacentes
  • trazado del histograma resultante con Matplotlib, pandas, y Seaborn

Free Bonus: Tienes poco tiempo? Haga clic aquí para obtener acceso a una conexión de dos páginas Python histogramas de hoja de trucos que resume las técnicas explicadas en este tutorial.

histogramas en Python puro

cuando se está preparando para trazar un histograma, lo más sencillo es no pensar en términos de contenedores sino informar cuántas veces aparece cada valor (una tabla de frecuencias). diccionario A Python está bien adaptado para esta tarea: count_elements

>>> # Need not be sorted, necessarily
>>> a = (0, 1, 1, 1, 2, 3, 7, 7, 23)

>>> def count_elements(seq) -> dict:
... """Tally elements from `seq`."""
... hist = {}
... for i in seq:
... hist[i] = hist.get(i, 0) + 1
... return hist

>>> counted = count_elements(a)
>>> counted
{0: 1, 1: 3, 2: 1, 3: 1, 7: 2, 23: 1}

() devuelve un diccionario con elementos únicos de la secuencia como claves y sus frecuencias (conteos) como valores. Dentro del bucle sobre ss, hist [i] = hist.get (i, 0) + 1 dice: “para cada elemento de la secuencia, incrementar su valor correspondiente en hist por 1.”

De hecho, esto es precisamente lo que se hace por la clase collections.Counter de la biblioteca estándar de Python, que subclases un pitón diccionario y anula su .Update () Método:

>>> from collections import Counter

>>> recounted = Counter(a)
>>> recounted
Counter({0: 1, 1: 3, 3: 1, 2: 1, 7: 2, 23: 1})

Puede confirmar que la función de su mano hace prácticamente el mismo cosa como collections.Counter ensayando para la igualdad entre los dos:

>>> recounted.items() == counted.items()
True

Detalle técnica : el mapeo de count_elements () por encima de los valores predeterminados a una función C más altamente optimizado si está disponible. Dentro de las funciones de Python (count_elements), una micro-optimización que podría hacer es declarar get = hist.get antes de que el ciclo for. Esto obligaría a un método a una variable para las llamadas más rápido dentro del bucle.

Puede ser útil para construir funciones simplificadas desde cero como un primer paso para entender las más complejas. más reinventar la rueda Vamos un poco con un histograma ASCII que se aprovecha de la producción de Python formateo:

def ascii_histogram(seq) -> None:
"""A horizontal frequency-table/histogram plot."""
counted = count_elements(seq)
for k in sorted(counted):
print('{0:5d} {1}'.format(k, '+' * counted[k]))

Esta función crea un gráfico de frecuencia ordenada, donde los recuentos son representados como recuentos de más símbolos (+). Llamando ordenados () en un diccionario devuelve una lista ordenada de sus llaves, y luego se accede al valor correspondiente para cada uno con contadas [k]. Para ver esto en acción, puede crear un conjunto de datos un poco más grande con el módulo de Python al azar:

>>> # No NumPy ... yet
>>> import random
>>> random.seed(1)

>>> vals = [1, 3, 4, 6, 8, 9, 10]
>>> # Each number in `vals` will occur between 5 and 15 times.
>>> freq = (random.randint(5, 15) for _ in vals)

>>> data = []
>>> for f, v in zip(freq, vals):
... data.extend([v] * f)

>>> ascii_histogram(data)
1 +++++++
3 ++++++++++++++
4 ++++++
6 +++++++++
8 ++++++
9 ++++++++++++
10 ++++++++++++

Aquí, usted está simulando el desplume de Vals con frecuencias dadas por frec (una expresión generador). Los datos de muestra resultante se repite cada valor de Vals un cierto número de veces entre 5 y 15.

Nota : random.seed () es el uso de la semilla, o inicializar, el generador de números pseudoaleatorios subyacente (PRNG) utilizado por azar. Puede sonar como una contradicción, pero esta es una manera de hacer que los datos aleatorios reproducible y determinista. Es decir, si copia el código aquí como es, usted debe obtener exactamente el mismo histograma porque la primera llamada a random.randint () después de sembrar el generador producirá idénticos datos “al azar” utilizando el Mersenne Twister.

, construyendo desde la base: Cálculos de histograma en NumPy

hasta ahora, que han estado trabajando con lo mejor que podría llamarse “tablas de frecuencia.” Pero matemáticamente, un histograma es una asignación de intervalos (intervalos) para frecuencias. Más técnicamente, se puede utilizar para aproximar la función de densidad de probabilidad (PDF) de la variable subyacente.

Pasando de la “tabla de frecuencias” anterior, un verdadero histograma primeros “contenedores” de la gama de valores y luego cuenta el número de valores que caen en cada bin. Esto es lo que hace la función de histograma NumPy (), y es la base para otras funciones que verá aquí más tarde en las bibliotecas de Python como Matplotlib y pandas.

Considere una muestra de flotadores extraídas de la distribución de Laplace. Esta distribución de los extremos son mayores que una distribución normal y tiene dos parámetros descriptivos (localización y escala):

>>> import numpy as np
>>> # `numpy.random` uses its own PRNG.
>>> np.random.seed(444)
>>> np.set_printoptions(precision=3)

>>> d = np.random.laplace(loc=15, scale=3, size=500)
>>> d[:5]
array([18.406, 18.087, 16.004, 16.221, 7.358])

En este caso, se trabaja con una distribución continua, y no sería muy útil para anotar cada flotador de forma independiente, hasta la enésima decimal. En su lugar, puede cubo o “cubo” los datos y cuenta las observaciones que caen en cada bandeja. El histograma es el recuento resultante de los valores dentro de cada bin:

>>> hist, bin_edges = np.histogram(d)

>>> hist
array([ 1, 0, 3, 4, 4, 10, 13, 9, 2, 4])

>>> bin_edges
array([ 3.217, 5.199, 7.181, 9.163, 11.145, 13.127, 15.109, 17.091,
19.073, 21.055, 23.037])

Este resultado puede no ser inmediatamente intuitiva. np.histogram () de forma predeterminada utiliza 10 contenedores de igual tamaño y devuelve una tupla de los conteos de frecuencia y los correspondientes bordes de basura. Son bordes en el sentido de que habrá un borde más papelera que hay miembros del histograma:

>>> hist.size, bin_edges.size
(10, 11)

Detalle técnico : Todos excepto el último (más a la derecha) bin está entreabierta. Es decir, todos los contenedores, pero los últimos son [incluido, exclusivo), y la última es bin [incluido, incluido].

un desglose muy condensada de cómo los contenedores son construidos por NumPy se ve así:

>>> # The leftmost and rightmost bin edges
>>> first_edge, last_edge = a.min(), a.max()

>>> n_equal_bins = 10 # NumPy's default
>>> bin_edges = np.linspace(start=first_edge, stop=last_edge,
... num=n_equal_bins + 1, endpoint=True)
...
>>> bin_edges
array([ 0. , 2.3, 4.6, 6.9, 9.2, 11.5, 13.8, 16.1, 18.4, 20.7, 23. ])

El caso anterior tiene mucho sentido: 10 bins igualmente espaciados en un intervalo de pico a pico de 23 medios intervalos de anchura 2,3.

A partir de ahí, los delegados función a np.bincount () o np.searchsorted (). bincount () en sí mismo puede ser utilizado para construir efectivamente la “tabla de frecuencias” que inició con aquí, con la diferencia de que los valores con cero ocurrencias se incluyen:

>>> bcounts = np.bincount(a)
>>> hist, _ = np.histogram(a, range=(0, a.max()), bins=a.max() + 1)

>>> np.array_equal(hist, bcounts)
True

>>> # Reproducing `collections.Counter`
>>> dict(zip(np.unique(a), bcounts[bcounts.nonzero()]))
{0: 1, 1: 3, 2: 1, 3: 1, 7: 2, 23: 1}

Nota : hist aquí es realmente utiliza contenedores de ancho de 1,0 en vez que cuenta “discretas”. Por lo tanto, esto sólo funciona para los números enteros de conteo, no flota como [3.9, 4.1, 4.15].

Visualizando histogramas con Matplotlib y pandas

Ahora que usted ha visto cómo construir un histograma en Python desde el principio, vamos a ver cómo otros paquetes de Python pueden hacer el trabajo para usted. Matplotlib proporciona la funcionalidad para visualizar Python histogramas fuera de la caja con una envoltura versátil alrededor de histograma de NumPy ():

import matplotlib.pyplot as plt

# An "interface" to matplotlib.axes.Axes.hist() method
n, bins, patches = plt.hist(x=d, bins='auto', color='#0504aa',
alpha=0.7, rwidth=0.85)
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.title('My Very Own Histogram')
plt.text(23, 45, r'$\mu=15, b=3$')
maxfreq = n.max()
# Set a clean upper y-axis limit.
plt.ylim(ymax=np.ceil(maxfreq / 10) * 10 if maxfreq % 10 else maxfreq + 10)

Tal como se define anteriormente, una trama de un histograma utiliza sus bordes bin en el eje x y las frecuencias correspondientes en el eje y. En la tabla de arriba, pasando bins = elige ‘auto’ entre dos algoritmos para estimar el número “ideal” de bins. En un nivel alto, el objetivo del algoritmo es elegir una anchura bin que genera la representación más fiel de los datos. Para más información sobre este tema, que puede ser bastante técnica, echa un vistazo a elección de los compartimientos de histograma de los documentos Astropy.

Permanecer en la pila científica de Python, Series.histogram pandas’ () utiliza matplotlib.pyplot.hist () para dibujar un histograma Matplotlib de la entrada de la serie:

import pandas as pd

# Generate data on commute times.
size, scale = 1000, 10
commutes = pd.Series(np.random.gamma(scale, size=size) ** 1.5)

commutes.plot.hist(grid=True, bins=20, rwidth=0.9,
color='#607c8e')
plt.title('Commute Times for 1,000 Commuters')
plt.xlabel('Counts')
plt.ylabel('Commute Time')
plt.grid(axis='y', alpha=0.75)

pandas.DataFrame.histogram () es similar, pero produce una histograma para cada columna de datos de la trama de datos.

trazado una estimación de densidad de Kernel (KDE)

En este tutorial, usted ha estado trabajando con las muestras, estadísticamente hablando. Si los datos se discreto o continuo, se supone que se derivan de una población que tiene una verdadera distribución, exacto descrito por sólo unos pocos parámetros.

Una estimación de la densidad del núcleo (KDE) es una manera de estimar la función de densidad de probabilidad (PDF) de la variable aleatoria que “subyace” nuestra muestra. KDE es un medio de alisado de datos.

Siguiendo con la biblioteca pandas, puede crear gráficos de densidad y de superposición en plot.kde (), que está disponible tanto para la serie y la trama de datos de objetos. Pero primero, vamos a generar dos muestras distintas de datos para la comparación:

>>> # Sample from two different normal distributions
>>> means = 10, 20
>>> stdevs = 4, 2
>>> dist = pd.DataFrame(
... np.random.normal(loc=means, scale=stdevs, size=(1000, 2)),
... columns=['a', 'b'])
>>> dist.agg(['min', 'max', 'mean', 'std']).round(decimals=2)
a b
min -1.57 12.46
max 25.32 26.44
mean 10.12 19.94
std 3.94 1.94

Ahora, para trazar cada histograma en los mismos ejes matplotlib:

fig, ax = plt.subplots()
dist.plot.kde(ax=ax, legend=False, title='Histogram: A vs. B')
dist.plot.hist(density=True, ax=ax)
ax.set_ylabel('Probability')
ax.grid(axis='y')
ax.set_facecolor('#d8dcd6')

Estos métodos de apalancamiento gaussian_kde de SciPy (), que se traduce en una más suave de aspecto PDF.

Si usted echa un vistazo más de cerca a esta función, se puede ver lo bien que se aproxima a la “verdadera” PDF para una muestra relativamente pequeña de 1.000 puntos de datos. A continuación, se puede construir primero la distribución “analítica” con scipy.stats.norm (). Esta es una instancia de clase que encapsula la distribución estadística estándar normal, sus momentos, y las funciones descriptivas. Su PDF es “exacta” en el sentido de que se define precisamente como norm.pdf (x) = exp (-x ** 2/2) / sqrt (2 * pi).

de construcción a partir de ahí, se puede tomar una muestra aleatoria de 1000 puntos de datos de esta distribución, a continuación, tratar de nuevo en una estimación de la PDF con scipy.stats.gaussian_kde ():

from scipy import stats

# An object representing the "frozen" analytical distribution
# Defaults to the standard normal distribution, N~(0, 1)
dist = stats.norm()

# Draw random samples from the population you built above.
# This is just a sample, so the mean and std. deviation should
# be close to (1, 0).
samp = dist.rvs(size=1000)

# `ppf()`: percent point function (inverse of cdf — percentiles).
x = np.linspace(start=stats.norm.ppf(0.01),
stop=stats.norm.ppf(0.99), num=250)
gkde = stats.gaussian_kde(dataset=samp)

# `gkde.evaluate()` estimates the PDF itself.
fig, ax = plt.subplots()
ax.plot(x, dist.pdf(x), linestyle='solid', c='red', lw=3,
alpha=0.8, label='Analytical (True) PDF')
ax.plot(x, gkde.evaluate(x), linestyle='dashed', c='black', lw=2,
label='PDF Estimated via KDE')
ax.legend(loc='best', frameon=False)
ax.set_title('Analytical vs. Estimated PDF')
ax.set_ylabel('Probability')
ax.text(-2., 0.35, r'$f(x) = \frac{\exp(-x^2/2)}{\sqrt{2*\pi}}$',
fontsize=12)

Se trata de un pedazo más grande de código, por lo que vamos a echar un segundo para tocar en algunas líneas fundamentales: subpaquete

  • SciPy de estadísticas le permite crear objetos de Python que representan las distribuciones de análisis que se puede degustar de crear datos reales. Así dist = stats.norm (), representa la variable aleatoria continua normal, y se genera números aleatorios de ella con dist.rvs ().
  • para evaluar tanto el PDF analítica y la de Gauss KDE, que necesitan una matriz x de los cuantiles (desviaciones estándar por encima / debajo de la media, para una distribución normal). stats.gaussian_kde () representa un PDF estimado que es necesario evaluar en una matriz para producir algo visualmente significativa en este caso.
  • La última línea contiene un poco de látex, que se integra muy bien con Matplotlib.

una fantasía alternativa con Seaborn

Vamos a traer un paquete de Python más en la mezcla. Seaborn tiene una función displot () que traza el histograma y KDE para una distribución univariante en un solo paso. Uso de la matriz NumPy d de ealier:

import seaborn as sns

sns.set_style('darkgrid')
sns.distplot(d)

La llamada anterior produce una KDE. También hay opcionalidad para adaptarse a una distribución específica de los datos. Esto es diferente de una KDE y consiste en la estimación de parámetros para los datos genéricos y un nombre de distribución especificada:

sns.distplot(d, fit=stats.laplace, kde=False)

Una vez más, tenga en cuenta la ligera diferencia. En el primer caso, se está realizando la estimación alguna PDF desconocida; en la segunda, que está teniendo una distribución conocida y encontrar qué parámetros describiría mejor dado los datos empíricos.

Otras herramientas de pandas

Además de sus herramientas de trazado, pandas también ofrece una .value_counts convenientes () que calcula un histograma de valores no nulos a una serie pandas:

>>> import pandas as pd

>>> data = np.random.choice(np.arange(10), size=10000,
... p=np.linspace(1, 11, 10) / 60)
>>> s = pd.Series(data)

>>> s.value_counts()
9 1831
8 1624
7 1423
6 1323
5 1089
4 888
3 770
2 535
1 347
0 170
dtype: int64

>>> s.value_counts(normalize=True).head()
9 0.1831
8 0.1624
7 0.1423
6 0.1323
5 0.1089
dtype: float64

Por otra parte, pandas.cut () es una forma conveniente de los valores de bin en intervalos arbitrarios. Digamos que usted tiene algunos datos sobre las edades de los individuos y desea cucharón con sensatez: de

>>> ages = pd.Series(
... [1, 1, 3, 5, 8, 10, 12, 15, 18, 18, 19, 20, 25, 30, 40, 51, 52])
>>> bins = (0, 10, 13, 18, 21, np.inf) # The edges
>>> labels = ('child', 'preteen', 'teen', 'military_age', 'adult')
>>> groups = pd.cut(ages, bins=bins, labels=labels)

>>> groups.value_counts()
child 6
adult 5
teen 3
military_age 2
preteen 1
dtype: int64

>>> pd.concat((ages, groups), axis=1).rename(columns={0: 'age', 1: 'group'})
age group
0 1 child
1 1 child
2 3 child
3 5 child
4 8 child
5 10 child
6 12 preteen
7 15 teen
8 18 teen
9 18 teen
10 19 military_age
11 20 military_age
12 25 adult
13 30 adult
14 40 adult
15 51 adult
16 52 adult

Lo bueno es que estas dos operaciones, en última instancia utilizan código Cython que los hace competitivos en la velocidad y manteniendo su flexibilidad.

bien, así que cuál debería usar?

En este punto, usted ha visto más de un puñado de funciones y métodos para elegir para trazar un histograma Python. ¿Cómo se comparan? En resumen, no hay “una talla única para todos.” He aquí un resumen de las funciones y métodos que ha cubierto hasta el momento, todos los cuales se refieren a romper y que representa distribuciones en Python: Bonus

gratuito: Tienes poco tiempo? Haga clic aquí para obtener acceso a una conexión de dos páginas Python histogramas de hoja de trucos que resume las técnicas explicadas en este tutorial.

También puede encontrar los fragmentos de código de este artículo juntos en una secuencia de comandos en la página de materiales real del pitón.

Con eso, la buena suerte la creación de histogramas en la naturaleza. Con suerte una de las herramientas más arriba se adapte a sus necesidades. Cualquier cosa que hagas, simplemente no utilizar un gráfico circular.

Mira ahora Este tutorial tiene un vídeo relacionado curso creado por el equipo del Real Python. Mira que junto con el tutorial escrito para profundizar su comprensión: Python histograma Trazado: NumPy, Matplotlib, pandas y Seaborn

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *