Categorías
Python

Aplicaciones Web con el frasco Python – Parte II

 

Tabla de Contenidos

  • limpieza
  • Ejemplo 1: EE.UU. Congreso DatasetThe “Hola, mundo!” de pandas GroupByPandas GroupBy vs SQLHow pandas GroupBy Obras
  • El “Hola, mundo!” de pandas GroupBy
  • pandas GroupBy vs SQL
  • Cómo pandas GroupBy Obras
  • Ejemplo 2: Calidad del aire en DatasetGrouping Derivado ArraysResampling
  • Agrupación de matrices Derivado
  • remuestreo
  • Ejemplo 3: Funciones agregador de noticias DatasetUsing Lambda en .groupby () Mejora del rendimiento del .groupby ()
  • Uso de las funciones Lambda en .groupby ()
  • mejorar el rendimiento de .groupby ()
  • pandas GroupBy: Poniendo todo junto
  • Conclusión
  • Más Recursos de pandas GroupBy
    El

  • “Hola, mundo!” de pandas GroupBy
  • pandas GroupBy vs SQL
  • Cómo pandas GroupBy Obras
  • Agrupación de matrices Derivado
  • remuestreo
  • Uso de las funciones Lambda en .groupby ()
  • mejorar el rendimiento de .groupby ()

Tanto si acabas de empezar a trabajar con las pandas y desea un maestro de sus instalaciones centrales, o usted está mirando para llenar algunas lagunas en su comprensión acerca de .groupby (), este tutorial le ayudará a romper hacia abajo y visualizar una operación pandas GroupBy de principio a fin.

Este tutorial está destinado a complementar la documentación oficial, donde puedes encontrar ejemplos, tamaño de un bocado autónomos. Aquí, sin embargo, usted se centran en tres paseos virtuales más complicados que utilizan conjuntos de datos del mundo real.

En este tutorial, usted cubrirá:

  • Cómo utilizar las operaciones de pandas GroupBy en los datos del mundo real
  • Cómo aplicar la escisión-combinar la cadena de operaciones funciona
  • cómo descomponer la fracción de apply- combinar la cadena en pasos
  • cómo los métodos de un objeto pandas GroupBy se pueden colocar en diferentes categorías en función de su intención y el resultado

Este tutorial asume que tienes alguna experiencia con ella misma pandas, incluyendo cómo leer archivos CSV en la memoria como objetos pandas con read_csv (). Si usted necesita un repaso, a continuación, echa un vistazo a la lectura CSVs Con pandas.

Puede descargar el código fuente de todos los ejemplos de este tutorial haciendo clic en el siguiente enlace:

descargar conjuntos de datos: Haga clic aquí para descargar los conjuntos de datos que utilizará para aprender acerca de las pandas’ GroupBy en este tutorial.

limpieza

Todo el código en este tutorial fue generada en un 3.7.2 shell CPython usando pandas 0.25.0. Antes de continuar, asegúrese de que usted tiene la última versión de pandas disponibles dentro de un nuevo entorno virtual:

$ python -m venv pandas-gb-tut
$ source ./pandas-gb-tut/bin/activate
$ python -m pip install pandas

Los ejemplos aquí también utilizan algunas opciones pandas pellizcadas para la salida amigable:

import pandas as pd

# Use 3 decimal places in output display
pd.set_option("display.precision", 3)

# Don't wrap repr(DataFrame) across additional lines
pd.set_option("display.expand_frame_repr", False)

# Set max rows displayed in output to 25
pd.set_option("display.max_rows", 25)

Usted puede añadir estos a un archivo de inicio de establecer de forma automática cada vez que se arranca el intérprete.

En este tutorial, se centran en tres conjuntos de datos:

Usted puede descargar el código fuente de todos los ejemplos de este tutorial haciendo clic en el siguiente enlace:

descargar conjuntos de datos: Haga clic aquí para descargar los conjuntos de datos que ‘ll utilizar para conocer las pandas’ GroupBy en este tutorial.

Una vez que haya descargado el .zip, puede descomprimirlo en el directorio actual:

$ unzip -q -d groupby-data groupby-data.zip

La opción -d le permite extraer el contenido a una nueva carpeta:

./

└── groupby-data/

├── legislators-historical.csv
├── airqual.csv
└── news.csv

Con que vayan a crear, ya está listo para ¡saltar!

Ejemplo 1: Congreso EE.UU. conjunto de datos

Vas a entrar de lleno en las cosas mediante la disección de un conjunto de datos históricos de los miembros del Congreso. Usted puede leer el archivo CSV en un pandas trama de datos con read_csv ():

import pandas as pd

dtypes = {
"first_name": "category",
"gender": "category",
"type": "category",
"state": "category",
"party": "category",
}
df = pd.read_csv(
"groupby-data/legislators-historical.csv",
dtype=dtypes,
usecols=list(dtypes) + ["birthday", "last_name"],
parse_dates=["birthday"]
)

El conjunto de datos contiene el nombre y apellido, fecha de nacimiento, sexo, tipo ( ‘representante’ para la Cámara de Representantes o ‘sen’ para el Senado) de los miembros, estado de Estados Unidos, y el partido político. Puede utilizar df.tail () para competir las últimas hileras del conjunto de datos:

>>> df.tail()
last_name first_name birthday gender type state party
11970 Garrett Thomas 1972-03-27 M rep VA Republican
11971 Handel Karen 1962-04-18 F rep GA Republican
11972 Jones Brenda 1959-10-24 F rep MI Democrat
11973 Marino Tom 1952-08-15 M rep PA Republican
11974 Jones Walter 1943-02-10 M rep NC Republican

La trama de datos utiliza categórica dtypes para la eficiencia del espacio:

>>> df.dtypes
last_name object
first_name category
birthday datetime64[ns]
gender category
type category
state category
party category
dtype: object

se puede ver que la mayoría de las columnas del conjunto de datos tienen la categoría de tipo, que reduce la carga de memoria en su máquina.

El “Hola, mundo!” de pandas GroupBy

Ahora que usted está familiarizado con el conjunto de datos, usted comenzará con un “Hola, Mundo!” para la operación de las pandas GroupBy. ¿Cuál es el recuento de los miembros del Congreso, sobre una base de estado por estado, en toda la historia del conjunto de datos? En SQL, se puede encontrar esta respuesta con una instrucción SELECT:

SELECT state, count(name)
FROM df
GROUP BY state
ORDER BY state;

Aquí está la casi equivalente en pandas:

>>> n_by_state = df.groupby("state")["last_name"].count()
>>> n_by_state.head(10)
state
AK 16
AL 206
AR 117
AS 2
AZ 48
CA 361
CO 90
CT 240
DC 2
DE 97
Name: last_name, dtype: int64

usted llama .groupby () y pasar el nombre de la columna que desea agrupar, que es el «estado «. A continuación, utilice [ «apellidos»] para especificar las columnas sobre las que se desea realizar la agregación real.

Puede pasar mucho más que un solo nombre de columna a .groupby () como primer argumento. También puede especificar cualquiera de los siguientes:

  • una lista de varios nombres de columna
  • un diccionario o matriz serie pandas
  • Un NumPy o el índice de pandas, o un array como iterable de éstos

Aquí está un ejemplo de agrupación conjuntamente en dos columnas, que encuentra la cuenta de los miembros del Congreso desglosados ​​por estado y luego por género:

>>> df.groupby(["state", "gender"])["last_name"].count()
state gender
AK M 16
AL F 3
M 203
AR F 5
M 112
...
WI M 196
WV F 1
M 119
WY F 2
M 38
Name: last_name, Length: 104, dtype: int64

la consulta SQL análoga se vería así:

SELECT state, gender, count(name)
FROM df
GROUP BY state, gender
ORDER BY state, gender;

como se verá a continuación, .groupby () y el comparables sentencias SQL son primos cercanos, pero a menudo no son funcionalmente idénticos.

Nota : Hay una diferencia más pequeña en la comparación de las pandas GroupBy vs SQL aquí: en la versión pandas, algunos estados sólo muestran uno de los géneros. Durante el desarrollo de este tutorial, nos encontramos con un pequeño pero complicado fallo en la fuente de pandas que no maneja el parámetro observado bien con ciertos tipos de datos. ¡Nunca temas! Hay algunas soluciones en este caso particular.

pandas GroupBy vs SQL

Este es un buen momento para introducir una diferencia importante entre la operación de pandas GroupBy y la consulta SQL anterior. El conjunto de resultados de la consulta SQL contiene tres columnas:

En la versión pandas, las luces agrupadas, en columnas son empujados a la MultiIndex de la serie resultante por defecto:

>>> n_by_state_gender = df.groupby(["state", "gender"])["last_name"].count()
>>> type(n_by_state_gender)

>>> n_by_state_gender.index[:5]
MultiIndex([('AK', 'M'),
('AL', 'F'),
('AL', 'M'),
('AR', 'F'),
('AR', 'M')],
names=['state', 'gender'])

para emular más de cerca el resultado de SQL y empuje el grouped- en las columnas de nuevo en columnas en el resultado, un as_index uso = False:

>>> df.groupby(["state", "gender"], as_index=False)["last_name"].count()
state gender last_name
0 AK F NaN
1 AK M 16.0
2 AL F 3.0
3 AL M 203.0
4 AR F 5.0
.. ... ... ...
111 WI M 196.0
112 WV F 1.0
113 WV M 119.0
114 WY F 2.0
115 WY M 38.0

[116 rows x 3 columns]

Esto produce una trama de datos con tres columnas y un RangeIndex, en lugar de una serie con un MultiIndex. En resumen, el uso de as_index = False hará que su resultado más estrechamente imitan la salida de SQL por defecto para una operación similar.

Nota : En df.groupby ([ «Estado», «género»]) [ «apellidos»] count (), también se puede utilizar .size () en lugar de .count (), ya lo sabes. no hay apellidos NaN. Usando .count () excluye valores NaN, mientras .size () incluye todo, NaN o no.

nota también de que las consultas SQL anterior utilizan explícitamente ORDER BY, mientras que .groupby () no lo hace. Esto se debe a .groupby () hace esto por defecto a través de su parámetro de clasificación, lo cual es cierto a menos que usted le indique lo contrario:

>>> # Don't sort results by the sort keys
>>> df.groupby("state", sort=False)["last_name"].count()
state
DE 97
VA 432
SC 251
MD 305
PA 1053
...
AK 16
PI 13
VI 4
GU 4
AS 2
Name: last_name, Length: 58, dtype: int64

A continuación, deberá sumergirse en el objeto que .groupby () produce realmente.

Cómo pandas GroupBy Obras

Antes de llegar más lejos en los detalles, tome un paso atrás para mirar a .groupby () sí:

>>> by_state = df.groupby("state")
>>> print(by_state)

¿Qué es esa cosa DataFrameGroupBy? Su .__ __ str () no le da mucha información sobre lo que realmente es o cómo funciona. La razón de que un objeto DataFrameGroupBy puede ser difícil de envolver su cabeza alrededor es que es perezosa en la naturaleza. En realidad, no hacer ninguna operación para producir un resultado útil hasta que usted lo dice.

Un término que se utiliza con frecuencia junto .groupby () es split-apply-combinan . Esto se refiere a una cadena de tres pasos:

Puede ser difícil para inspeccionar df.groupby ( «Estado»), ya que hace prácticamente ninguna de estas cosas hasta que haga algo con el objeto resultante. Una vez más, un objeto de pandas GroupBy es perezoso. Retrasa virtualmente cada parte del proceso a aplicar-se combinan dividida hasta que invocar un método en él.

Así que, ¿cómo se puede separar mentalmente la división, aplicar y combinar etapas si no puede ver cualquiera de ellos ocurre en el aislamiento? Una forma útil para inspeccionar un objeto pandas GroupBy y ver la división en acción es iterar sobre ella. Esto se implementa en DataFrameGroupBy .__ iter __ () y produce un iterador de ( grupo trama de datos) pares de tramas de datos:

>>> for state, frame in by_state:
... print(f"First 2 entries for {state!r}")
... print("------------------------")
... print(frame.head(2), end="\n\n")
...
First 2 entries for 'AK'
------------------------
last_name first_name birthday gender type state party
6619 Waskey Frank 1875-04-20 M rep AK Democrat
6647 Cale Thomas 1848-09-17 M rep AK Independent

First 2 entries for 'AL'
------------------------
last_name first_name birthday gender type state party
912 Crowell John 1780-09-18 M rep AL Republican
991 Walker John 1783-08-12 M sen AL Republican

Si está trabajando en un problema de agregación desafiante, a continuación, iterar sobre el objeto pandas GroupBy puede ser una gran manera de visualizar la divide parte de divide -Aplicar-combinan.

Hay algunos otros métodos y propiedades que permiten que usted mira en los grupos individuales y sus divisiones. El atributo .Grupos le dará un diccionario de {nombre del grupo: grupo de etiquetas} pares. Por ejemplo, by_state es un diccionario con los estados como llaves. Aquí está el valor de la clave «PA»:

>>> by_state.groups["PA"]
Int64Index([ 4, 19, 21, 27, 38, 57, 69, 76, 84,
88,
...
11842, 11866, 11875, 11877, 11887, 11891, 11932, 11945, 11959,
11973],
dtype='int64', length=1053)

Cada valor es una secuencia de los lugares de índice para las filas que pertenecen a ese grupo en particular. En la salida anterior, 4 , 19 , y 21 son los primeros índices en df en el que el estado es igual a “PA”.

También puede utilizar .get_group () como una forma de profundizar en la sub-tabla a partir de un solo grupo:

>>> by_state.get_group("PA")
last_name first_name birthday gender type state party
4 Clymer George 1739-03-16 M rep PA NaN
19 Maclay William 1737-07-20 M sen PA Anti-Administration
21 Morris Robert 1734-01-20 M sen PA Pro-Administration
27 Wynkoop Henry 1737-03-02 M rep PA NaN
38 Jacobs Israel 1726-06-09 M rep PA NaN
... ... ... ... ... ... ... ...
11891 Brady Robert 1945-04-07 M rep PA Democrat
11932 Shuster Bill 1961-01-10 M rep PA Republican
11945 Rothfus Keith 1962-04-25 M rep PA Republican
11959 Costello Ryan 1976-09-07 M rep PA Republican
11973 Marino Tom 1952-08-15 M rep PA Republican

Esto es prácticamente equivalente a usar .loc []. Usted podría conseguir el mismo resultado con algo como df.loc [df [ «estado»] == «PA»].

Nota : Yo uso el término genérico objeto pandas GroupBy para referirse tanto a un objeto o un objeto DataFrameGroupBy SeriesGroupBy, que tienen una gran cantidad de puntos en común entre ellos. También vale la pena mencionar de

Es que .groupby () hace hacer alguna , pero no todos, de los trabajos de división mediante la creación de una instancia de clase de agrupación para cada tecla que se pasa. Sin embargo, muchos de los métodos de la clase BaseGrouper que mantiene estas agrupaciones son llamados con pereza en lugar de en __init __ (), y muchos utilizan un diseño de la propiedad en caché.

A continuación, ¿qué pasa con la aplica parte? Se puede pensar en este paso del proceso, se aplica ing la misma operación (o exigible) para cada “sub-tabla” que se produce por la etapa de división. (No sé si “sub-tabla” es el término técnico, pero no he encontrado uno mejor ♂️)

Desde el objeto by_state pandas GroupBy, se puede agarrar el estado inicial de Estados Unidos y con la trama de datos próxima (). Al iterar sobre un objeto pandas GroupBy, obtendrá pares que se puede descomprimir en dos variables:

>>> state, frame = next(iter(by_state)) # First tuple from iterator
>>> state
'AK'
>>> frame.head(3)
last_name first_name birthday gender type state party
6619 Waskey Frank 1875-04-20 M rep AK Democrat
6647 Cale Thomas 1848-09-17 M rep AK Independent
7442 Grigsby George 1874-12-02 M rep AK NaN

Ahora, piense de nuevo a su original, la operación completa:

>>> df.groupby("state")["last_name"].count()
state
AK 16
AL 206
AR 117
AS 2
AZ 48
...

El aplicar etapa , cuando se aplica a un solo , con subjuegos trama de datos, se vería así:

>>> frame["last_name"].count() # Count for state == 'AK'
16

Se puede ver que el resultado, 16, coincide con el valor de AK en el resultado combinado.

El último paso, combinan , es el más fáciles de entender. Simplemente toma los resultados de todas las operaciones que apliquen en todas las sub-tablas y combinan s de nuevo juntos de una manera intuitiva.

Ejemplo 2: Calidad del Aire de conjunto de datos

El conjunto de datos de calidad del aire contiene lecturas por hora a partir de un dispositivo sensor de gas en Italia. Los valores perdidos se denotan con -200 en el archivo CSV. Puede utilizar read_csv () para combinar dos columnas en una marca de tiempo mientras se utiliza un subconjunto de las otras columnas:

import pandas as pd

df = pd.read_csv(
"groupby-data/airqual.csv",
parse_dates=[["Date", "Time"]],
na_values=[-200],
usecols=["Date", "Time", "CO(GT)", "T", "RH", "AH"]
).rename(
columns={
"CO(GT)": "co",
"Date_Time": "tstamp",
"T": "temp_c",
"RH": "rel_hum",
"AH": "abs_hum",
}
).set_index("tstamp")

Esto produce una trama de datos con un DatetimeIndex y cuatro columnas de flotación:

>>> df.head()
co temp_c rel_hum abs_hum
tstamp
2004-03-10 18:00:00 2.6 13.6 48.9 0.758
2004-03-10 19:00:00 2.0 13.3 47.7 0.726
2004-03-10 20:00:00 2.2 11.9 54.0 0.750
2004-03-10 21:00:00 2.2 11.0 60.0 0.787
2004-03-10 22:00:00 1.6 11.2 59.6 0.789

Aquí, co es una lectura promedio de monóxido de carbono de esa hora , mientras temp_c, rel_hum, y abs_hum son la temperatura media en grados Celsius, humedad relativa, y la humedad absoluta sobre esa hora, respectivamente. Las observaciones correr a partir de marzo de 2004 hasta Abril de 2005:

>>> df.index.min()
Timestamp('2004-03-10 18:00:00')
>>> df.index.max()
Timestamp('2005-04-04 14:00:00')

Hasta ahora, usted ha agrupados en columnas especificando sus nombres como str, como df.groupby ( «Estado»). Pero .groupby () es mucho más flexible que esto! Verá cómo siguiente.

Agrupación de matrices Derivado

Anteriormente se vio que el primer parámetro a .groupby () puede aceptar varios argumentos diferentes: la columna

  • A o lista de columnas
  • un diccionario o matriz serie pandas
  • Un NumPy o el índice de pandas , o una matriz similar a iterable de éstos

Usted puede tomar ventaja de la última opción para agrupar por el día de la semana. Puede utilizar .day_name del índice () para producir un índice de pandas de cadenas. Aquí están las diez primeras observaciones:

>>> day_names = df.index.day_name()
>>> type(day_names)

>>> day_names[:10]
Index(['Wednesday', 'Wednesday', 'Wednesday', 'Wednesday', 'Wednesday',
'Wednesday', 'Thursday', 'Thursday', 'Thursday', 'Thursday'],
dtype='object', name='tstamp')

A continuación, puede tomar este objeto y utilizarlo como la clave .groupby (). En pandas-hablar, day_names es array-como . Es una secuencia unidimensional de etiquetas.

Nota : Para una serie pandas, en lugar de un índice, necesitará el descriptor de acceso .dt para obtener acceso a métodos como .day_name (). Si Ser es tu serie, entonces se necesitaría ser.dt.day_name ().

Ahora, pasar ese objeto para .groupby () para encontrar el monóxido de carbono promedio () co) lectura por día de la semana:

>>> df.groupby(day_names)["co"].mean()
tstamp
Friday 2.543
Monday 2.017
Saturday 1.861
Sunday 1.438
Thursday 2.456
Tuesday 2.382
Wednesday 2.401
Name: co, dtype: float64

La fracción de aplicar-se comporta combinar procesos en gran medida el mismo que antes, excepto que el desdoblamiento esta vez se hace sobre una columna creada artificialmente. Esta columna no existe en la propia trama de datos, sino más bien se deriva de ella.

Lo que si se quería grupo no sólo por los días de la semana, sino por la hora del día? Ese resultado debería tener 7 * 24 = 168 observaciones. Para lograr esto, puede pasar una lista de objetos de matriz similar. En este caso, pasará pandas Int64Index objetos:

>>> hr = df.index.hour
>>> df.groupby([day_names, hr])["co"].mean().rename_axis(["dow", "hr"])
dow hr
Friday 0 1.936
1 1.609
2 1.172
3 0.887
4 0.823
...
Wednesday 19 4.147
20 3.845
21 2.898
22 2.102
23 1.938
Name: co, Length: 168, dtype: float64

Aquí está uno de los casos más similares que los usos .cut () a bin los valores de temperatura en intervalos discretos:

>>> bins = pd.cut(df["temp_c"], bins=3, labels=("cool", "warm", "hot"))
>>> df[["rel_hum", "abs_hum"]].groupby(bins).agg(["mean", "median"])
rel_hum abs_hum
mean median mean median
temp_c
cool 57.651 59.2 0.666 0.658
warm 49.383 49.3 1.183 1.145
hot 24.994 24.1 1.293 1.274

En este caso, los contenedores es en realidad una Serie:

>>> type(bins)

>>> bins.head()
tstamp
2004-03-10 18:00:00 cool
2004-03-10 19:00:00 cool
2004-03-10 20:00:00 cool
2004-03-10 21:00:00 cool
2004-03-10 22:00:00 cool
Name: temp_c, dtype: category
Categories (3, object): [cool < warm < hot]

Ya se trate de una matriz serie, NumPy o lista no importa. Lo que es importante es que los contenedores todavía sirve como una secuencia de etiquetas, una de fría, caliente o caliente. Si realmente quería, entonces también se podría utilizar una matriz categórica o incluso una lista simple de edad: Lista

  • nativo Python: df.groupby (bins.tolist ())
  • pandas categóricas matriz: df.groupby (contenedores .values)

Como se puede ver, .groupby () es inteligente y puede manejar una gran cantidad de diferentes tipos de entrada. Cualquiera de estos sería producir el mismo resultado porque todos ellos funcionan como una secuencia de etiquetas en el que realizar la agrupación y división.

remuestreo

vez agrupados df por el día de la semana con df.groupby (day_names) [ "co"]. Media (). Consideremos ahora algo diferente. ¿Y si quisiera agrupar por año y trimestre de una observación? He aquí una manera de lograr eso:

>>> # See an easier alternative below
>>> df.groupby([df.index.year, df.index.quarter])["co"].agg(
... ["max", "min"]
... ).rename_axis(["year", "quarter"])
max min
year quarter
2004 1 8.1 0.3
2 7.3 0.1
3 7.5 0.1
4 11.9 0.1
2005 1 8.7 0.1
2 5.0 0.3

Toda esta operación puede, alternativamente, ser expresada a través remuestreo . Uno de los usos de remuestreo es como GroupBy basado en el tiempo. Todo lo que necesita hacer es pasar una cadena de frecuencia, tales como "Q" de "trimestral", y pandas hará el resto:

>>> df.resample("Q")["co"].agg(["max", "min"])
max min
tstamp
2004-03-31 8.1 0.3
2004-06-30 7.3 0.1
2004-09-30 7.5 0.1
2004-12-31 11.9 0.1
2005-03-31 8.7 0.1
2005-06-30 5.0 0.3

A menudo, cuando se utiliza .resample () se puede expresar operaciones basadas en el tiempo en la agrupación de manera mucho más sucinta. El resultado puede ser un poco diferente pequeña que la más prolija .groupby () equivalente, pero a menudo encontrará que .resample () le da exactamente lo que estás buscando.

Ejemplo 3: agregador de noticias del conjunto de datos

Ahora se va a trabajar con el tercer y último conjunto de datos, que contiene los metadatos de varios cientos de miles de artículos de prensa y los agrupa en grupos de temas:

import datetime as dt
import pandas as pd

def parse_millisecond_timestamp(ts: int) -> dt.datetime:
"""Convert ms since Unix epoch to UTC datetime instance."""
return dt.datetime.fromtimestamp(ts / 1000, tz=dt.timezone.utc)

df = pd.read_csv(
"groupby-data
ews.csv",
sep="\t",
header=None,
index_col=0,
names=["title", "url", "outlet", "category", "cluster", "host", "tstamp"],
parse_dates=["tstamp"],
date_parser=parse_millisecond_timestamp,
dtype={
"outlet": "category",
"category": "category",
"cluster": "category",
"host": "category",
},
)

Para leer en la memoria con los dyptes adecuados , necesita una función de ayuda para analizar la columna de marca de tiempo. Esto es porque se expresa como el número de milisegundos desde la época Unix, en lugar de fracciones de segundo, que es la convención. Similar a lo que lo hacía antes, se puede utilizar el dtype categóricos para codificar eficientemente columnas que tienen un número relativamente pequeño de valores únicos en relación con la longitud de la columna.

Cada fila del conjunto de datos contiene el título, URL, nombre de la publicación de toma de corriente y de dominio, así como la fecha y hora de publicación. clúster es un ID aleatorio para el clúster tema al que pertenece un artículo. categoría es la categoría de noticias y contiene las siguientes opciones:

  • b por negocios
  • t para la ciencia y la tecnología
  • correo para el entretenimiento
  • m de la salud

He aquí la primera fila:

>>> df.iloc[0]
title Fed official says wea...
url http://www.latimes.co...
outlet Los Angeles Times
category b
cluster ddUyU0VZz0BRneMioxUPQ...
host www.latimes.com
tstamp 2014-03-10 16:52:50.6...
Name: 1, dtype: object

Ahora que ha tenía una visión de los datos, se puede empezar a hacer preguntas más complejas sobre ella.

Uso de las funciones Lambda en .groupby ()

invita este conjunto de datos mucho más potencialmente cuestiones involucradas. Voy a tirar al azar pero significativo por ahí: lo que los enchufes hablar más acerca de la Reserva Federal? Supongamos por simplicidad que esto conlleva en busca de mayúsculas y minúsculas menciones de "Fed". Tenga en cuenta que esto puede generar algunos falsos positivos con términos como “Gobierno Federal”. Para recuento

menciona por su salida, puede llamar .groupby () en la salida, y luego literalmente .apply () una función en cada grupo: la ruptura de

>>> df.groupby("outlet", sort=False)["title"].apply(
... lambda ser: ser.str.contains("Fed").sum()
... ).nlargest(10)
outlet
Reuters 161
NASDAQ 103
Businessweek 93
Investing.com 66
Wall Street Journal \(blog\) 61
MarketWatch 56
Moneynews 55
Bloomberg 53
GlobalPost 51
Economic Times 44
Name: title, dtype: int64

dejar que esta abajo, ya que hay varias llamadas a métodos realizados en sucesión. Al igual que antes, se puede sacar el primer grupo y su correspondiente objeto pandas tomando la primera tupla de los pandas GroupBy iterador:

>>> title, ser = next(iter(df.groupby("outlet", sort=False)["title"]))
>>> title
'Los Angeles Times'
>>> ser.head()
1 Fed official says weak data caused by weather,...
486 Stocks fall on discouraging news from Asia
1124 Clues to Genghis Khan's rise, written in the r...
1146 Elephants distinguish human voices by sex, age...
1237 Honda splits Acura into its own division to re...
Name: title, dtype: object

En este caso, ser una serie pandas en lugar de una trama de datos. Esto se debe a que siguió a la llamada .groupby () con [ "título"]. Esto selecciona eficazmente que una sola columna de cada sub-tabla.

Luego viene .str.contains ( "Fed"). Esto devuelve una serie booleano que es verdadera cuando un título del artículo registra una coincidencia en la búsqueda. Efectivamente, la primera fila comienza con "funcionario de la Fed dice que los datos débiles causados ​​por el clima, ..." y se ilumina como verdadera:

>>> ser.str.contains("Fed")
1 True
486 False
1124 False
1146 False
1237 False
...
421547 False
421584 False
421972 False
422226 False
422905 False
Name: title, Length: 1976, dtype: bool

El siguiente paso es .sum () esta serie. Desde bool es técnicamente sólo un tipo especializado de int, puede sumar una serie de verdadero y falso del mismo modo que resumir una secuencia de 1 y 0:

>>> ser.str.contains("Fed").sum()
17

El resultado es el número de menciones de "Fed" por el Los Angeles Times en el conjunto de datos. La misma rutina se aplica para Reuters, NASDAQ, Business Week, y el resto del lote.

mejorar el rendimiento de .groupby () de retroceso

Vamos de nuevo a .groupby (...). Apply () para ver por qué este patrón puede ser subóptima. Para obtener alguna información de fondo, echa un vistazo a Cómo acelerar su pandas Proyectos. Lo que puede ocurrir con .apply () es que va a realizar con eficacia un bucle Python sobre cada grupo. Mientras que el .groupby (...). Aplicar () patrón puede proporcionar una cierta flexibilidad, que puede también inhiben pandas de usar de otro modo sus optimizaciones basadas en Cython.

Todo lo que quiere decir que cada vez que se encuentra pensando en el uso de .apply (), preguntarse si hay una manera de expresar la operación de una forma vectorizada. En ese caso, se puede aprovechar el hecho de que .groupby () acepta no sólo uno o más nombres de columna, pero también muchos gama-como las estructuras :

  • A 1-dimensional array NumPy
  • Una lista
  • una serie pandas o índice

también tenga en cuenta que .groupby () es un método de instancia válida para una serie, no sólo una trama de datos, de modo que pueda esencialmente inversa a la lógica de dividir. Con esto en mente, primero puede construir una serie de booleanos que indican si el título contiene "Fed":

>>> mentions_fed = df["title"].str.contains("Fed")
>>> type(mentions_fed)

Ahora, .groupby () es también un método de la serie, por lo que puede agrupar una serie en otra:

>>> import numpy as np
>>> mentions_fed.groupby(
... df["outlet"], sort=False
... ).sum().nlargest(10).astype(np.uintc)
outlet
Reuters 161
NASDAQ 103
Businessweek 93
Investing.com 66
Wall Street Journal \(blog\) 61
MarketWatch 56
Moneynews 55
Bloomberg 53
GlobalPost 51
Economic Times 44
Name: title, dtype: uint32

las dos series no tienen que ser las columnas de un mismo objeto trama de datos. Sólo tienen que ser de la misma forma:

>>> mentions_fed.shape
(422419,)
>>> df["outlet"].shape
(422419,)

Por último, se puede emitir el resultado de vuelta a un entero sin signo con np.uintc si usted está decidido a obtener el resultado más compacto posible. He aquí una comparación cabeza a cabeza de las dos versiones que producirán el mismo resultado:

# Version 1: using `.apply()`
df.groupby("outlet", sort=False)["title"].apply(
lambda ser: ser.str.contains("Fed").sum()
).nlargest(10)

# Version 2: using vectorization
mentions_fed.groupby(
df["outlet"], sort=False
).sum().nlargest(10).astype(np.uintc)

En mi portátil, Versión 1 toma 4.01 segundos, mientras que la versión 2 tarda sólo 292 milisegundos. Se trata de una impresionante diferencia 14x en tiempo de CPU para un par de cientos de miles de filas. Tenga en cuenta cómo dramática la diferencia se hace cuando el conjunto de datos crece a unos pocos millones de filas!

Nota : Este ejemplo esmaltes sobre algunos detalles en los datos en aras de la simplicidad. A saber, el término de búsqueda "Fed" también puede encontrar menciones de cosas como “Gobierno Federal”.

Series.str.contains () también toma una expresión regular compilada como un argumento si se desea conseguir la suposición y el uso de una expresión que implica una búsqueda negativa hacia delante.

También puede querer contar no sólo el número de menciones en bruto, pero la proporción de menciones en relación con todos los artículos que produce un medio de comunicación.

pandas GroupBy: Poniendo todo junto

Si llama dir () en un objeto pandas GroupBy, entonces usted verá suficientes métodos allí para hacer girar su cabeza! Puede ser difícil hacer un seguimiento de toda la funcionalidad de un objeto pandas GroupBy. Una forma de despejar la niebla es compartimentar los diferentes métodos en lo que hacen y cómo se comportan.

En términos generales, los métodos de una caída objeto pandas GroupBy en un puñado de categorías: métodos

agregación (también llamado métodos de reducción ) “Smush” muchos puntos de datos en una estadística agregada acerca de esos puntos de datos. Un ejemplo es tomar la suma, la media o mediana de 10 números, donde el resultado es un solo número. Filtrar métodos

vienen de nuevo a usted con un subconjunto de la trama de datos originales. Esto significa más comúnmente usando .Filter () para soltar grupos enteros basado en alguna estadística comparativa sobre ese grupo y su sub-tabla. También tiene sentido para incluir en esta definición un número de métodos que excluyen filas específicas de cada grupo. Los métodos de transformación

devuelven una trama de datos con la misma forma y los índices como el original, pero con diferentes valores. Con ambos métodos de agregación y el filtro, la trama de datos resultante será comúnmente ser más pequeña en tamaño que la trama de datos de entrada. Esto no es cierto de una transformación, que transforma los valores individuales a sí mismos, pero conserva la forma de la trama de datos originales. métodos

Meta están menos preocupados con el objeto original en el que se ha llamado .groupby (), y más enfocado en darle información de alto nivel, tales como el número de grupos e índices de esos grupos. métodos

Trazado imitan la API de planear para una serie pandas o trama de datos, pero normalmente romper la salida en múltiples subtramas.

La documentación oficial tiene su propia explicación de estas categorías. Son, en cierto grado, abierto a la interpretación, y esto divergen fuerza tutorial en formas leves en la clasificación de qué método se cae dónde.

Nota: También hay otra tabla separada en la documentación pandas con su propio sistema de clasificación. Recoger lo que funciona para usted y parece más intuitivo!

Puede echar un vistazo a un desglose más detallado de cada categoría y los diversos métodos de .groupby () que se incluyen en ellos:

métodos de agregación y Propiedades mostrar / ocultar métodos

agregación (también llamados métodos de reducción de ) “Smush” muchos puntos de datos en una estadística agregada sobre los puntos de datos. Un ejemplo es tomar la suma, la media o mediana de 10 números, donde el resultado es un solo número. Aquí están algunos métodos de agregación:

  • .agg ()
  • .aggregate ()
  • .all ()
  • .any ()
  • .apply ()
  • .corr ()
  • .corrwith ()
  • .count ()
  • .cov ()
  • .cumcount ()
  • .cummax ()
  • .cummin ()
  • .cumprod ()
  • .cumsum ()
  • • Describir ()
  • . idxmax ()
  • .idxmin ()
  • .mad ()
  • .max ()
  • .mean ()
  • .median ()
  • .min ()
  • .nunique ()
  • .prod ( )
  • .sem ()
  • .size ()
  • .skew ()
  • .std ()
  • .sum ()
  • .var ()

Filtro Métodos y propiedades Mostrar / Ocultar

métodos de filtro volver a usted con un subconjunto de la trama de datos originales. Esto significa más comúnmente usando .Filter () para soltar grupos enteros basado en alguna estadística comparativa sobre ese grupo y su sub-tabla. También tiene sentido para incluir en esta definición un número de métodos que excluyen filas específicas de cada grupo. Aquí están algunos métodos de filtro:

  • .Filter ()
  • .First ()
  • .head ()
  • .last ()
  • .nth ()
  • .tail ()
  • .take ()

métodos de transformación y propiedades mostrar / ocultar

los métodos de transformación devuelve una trama de datos con la misma forma y los índices como el original, pero con diferentes valores. Con ambos métodos de agregación y el filtro, la trama de datos resultante será comúnmente ser más pequeña en tamaño que la trama de datos de entrada. Esto no es cierto de una transformación, que transforma los valores individuales a sí mismos, pero conserva la forma de la trama de datos originales. Aquí están algunos métodos de transformadores:

  • .bfill ()
  • .diff ()
  • .ffill ()
  • .fillna ()
  • .pct_change ()
  • .quantile ()
  • .rank ()
  • .shift ()
  • .transform ()
  • .tshift ()

métodos Meta y Propiedades Mostrar / Ocultar métodos

Meta tienen menos que ver con el objeto original en el que se ha llamado .groupby (), y más centrado en darle información de alto nivel, tales como el número de grupos e índices de esos grupos. Éstos son algunos métodos meta:

  • .__ __ (iter)
  • .get_group ()
  • .Grupos
  • .indices
  • .ndim
  • .ngroup

Métodos Trazado ()

  • .ngroups
  • .dtypes
  • Mostrar / Ocultar métodos

    trazado imitan la API de planear para una serie pandas o trama de datos, pero normalmente rompen la salida en múltiples subtramas. Aquí están algunos métodos de trazado:

    • .hist ()
    • .ohlc ()
    • .boxplot ()
    • .PLOT ()

    Odds and Ends Mostrar / Ocultar

    Hay algunos métodos de pandas GroupBy objetos que no están muy bien en las categorías anteriores. Estos métodos generalmente producen un objeto intermedio que es no una trama de datos o serie. . Por ejemplo, df.groupby (...) rodando (...) produce un objeto RollingGroupby, que se puede métodos de agregación, el filtro o de transformación continuación de compra sobre: ​​

    • .expanding ()
    • .pipe ()
    • .resample ()
    • .rolling ()

    Conclusión

    en este tutorial, que ha cubierto un montón de tierra en .groupby) (, incluyendo su diseño, su API, y la forma de la cadena de métodos en conjunto para obtener los datos en una salida que se adapte a su propósito.

    Usted ha aprendido:

    • Cómo utilizar las operaciones de pandas GroupBy en los datos del mundo real
    • Cómo aplicar la escisión-combinar la cadena de obras de operaciones y cómo se puede descomponer en pasos
    • cómo los métodos de una pandas GroupBy se puede colocar en diferentes categorías en función de su intención y el resultado

    Hay mucho más a .groupby () que se puede cubrir en un tutorial. Echa un vistazo a los siguientes recursos y el uso de los conjuntos de datos de ejemplo aquí como un punto de partida para una exploración más profunda!

    Puede descargar el código fuente de todos los ejemplos de este tutorial haciendo clic en el siguiente enlace:

    descargar conjuntos de datos: Haga clic aquí para descargar los conjuntos de datos que utilizará para aprender acerca de las pandas' GroupBy en este tutorial.

    Más recursos sobre guías de documentación pandas GroupBy

    pandas son fáciles de usar paseos virtuales a diferentes aspectos de las pandas. Aquí hay algunas partes de la documentación que se pueden extraer para aprender más acerca de las pandas GroupBy:

    • las pandas GroupBy guía del usuario
    • La Agrupación libro de cocina

    La documentación de la API es una referencia técnica más completa de métodos y objetos:

    • DataFrame.groupby ()
    • DataFrame.resample ()
    • pandas.Grouper

    Deja un comentario

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