python - Cómo asignar datos numéricos en categorías/bins en el marco de datos de Pandas
python-2.7 numpy (1)
Acabo de comenzar a codificar en Python, y mis habilidades generales de codificación son bastante oxidadas :( así que por favor sea un poco paciente
Tengo un marco de datos de pandas:
Tiene alrededor de 3m de hileras. Hay 3 tipos de unidades de edad: Y, D, W por años, días y semanas. Cualquier persona mayor de 1 año tiene una unidad de edad de Y y mi primer grupo que quiero es <2 años, así que todo lo que tengo que probar en las Unidades de Edad es Y ...
Quiero crear una nueva columna AgeRange y llenarla con los siguientes rangos:
- <2
- 2 - 18
- 18 - 35
- 35 - 65
- 65+
entonces escribí una función
def agerange(values):
for i in values:
if complete.Age_units == ''Y'':
if complete.Age > 1 AND < 18 return ''2-18''
elif complete.Age > 17 AND < 35 return ''18-35''
elif complete.Age > 34 AND < 65 return ''35-65''
elif complete.Age > 64 return ''65+''
else return ''< 2''
Pensé que si pasaba el marco de datos en su conjunto obtendría lo que necesitaba y luego podría crear la columna que quería algo como esto:
agedetails[''age_range''] = ageRange(agedetails)
PERO cuando intento ejecutar el primer código para crear la función que obtengo:
File "<ipython-input-124-cf39c7ce66d9>", line 4
if complete.Age > 1 AND complete.Age < 18 return ''2-18''
^
SyntaxError: invalid syntax
Claramente, no está aceptando el AND, pero pensé que escuché en clase que podría usar AND de esta manera. Debo estar equivocado, pero ¿cuál sería la forma correcta de hacer esto?
Entonces, después de obtener ese error, tampoco estoy seguro de que el método de pasar un marco de datos arroje un error. Supongo que probablemente sí. En cuyo caso, ¿cómo haría que eso funcione también?
Estoy buscando aprender el mejor método, pero parte del mejor método para mí es mantenerlo simple, incluso si eso significa hacer las cosas en un par de pasos ...
Con Pandas, debe evitar las operaciones a nivel de fila, ya que generalmente implican un bucle ineficiente a nivel de Python. Aquí hay un par de alternativas.
Pandas:
pd.cut
Como sugiere @JonClements, puede usar
pd.cut
para esto, el beneficio aquí es que su nueva columna se convierte en
Categorical
.
Solo necesita definir sus límites (incluyendo
np.inf
) y los nombres de categoría, luego aplique
pd.cut
a la columna numérica deseada.
bins = [0, 2, 18, 35, 65, np.inf]
names = [''<2'', ''2-18'', ''18-35'', ''35-65'', ''65+'']
df[''AgeRange''] = pd.cut(df[''Age''], bins, labels=names)
print(df.dtypes)
# Age int64
# Age_units object
# AgeRange category
# dtype: object
NumPy:
np.digitize
np.digitize
proporciona otra solución limpia.
La idea es definir sus límites y nombres, crear un diccionario y luego aplicar
np.digitize
a su columna Edad.
Finalmente, use su diccionario para mapear los nombres de sus categorías.
Tenga en cuenta que para los casos límite, el límite inferior se utiliza para asignar a un contenedor.
import pandas as pd, numpy as np
df = pd.DataFrame({''Age'': [99, 53, 71, 84, 84],
''Age_units'': [''Y'', ''Y'', ''Y'', ''Y'', ''Y'']})
bins = [0, 2, 18, 35, 65]
names = [''<2'', ''2-18'', ''18-35'', ''35-65'', ''65+'']
d = dict(enumerate(names, 1))
df[''AgeRange''] = np.vectorize(d.get)(np.digitize(df[''Age''], bins))
Resultado
Age Age_units AgeRange
0 99 Y 65+
1 53 Y 35-65
2 71 Y 65+
3 84 Y 65+
4 84 Y 65+