web-dev-qa-db-fra.com

Comment mapper des données numériques dans des catégories / bacs dans Pandas dataframe

Je viens de commencer à coder en python, et mes compétences générales en matière de codage sont assez rouillées :( alors s'il vous plaît soyez un peu patient

J'ai un pandas dataframe:

SamplePandas

Il a environ 3 m de rangées. Il existe 3 types d'unités d'âge: Y, D, W pour les années, les jours et les semaines. Toute personne de plus d'un an a une unité d'âge de Y et mon premier groupe que je veux est <2 ans, donc tout ce que je dois tester en unités d'âge est Y ...

Je veux créer une nouvelle colonne AgeRange et remplir les plages suivantes:

  • <2
  • 2 - 18
  • 18 - 35
  • 35 - 65
  • 65+

j'ai donc écrit une fonction

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'

Je pensais que si je passais dans la trame de données dans son ensemble, je récupérerais ce dont j'avais besoin et pourrais ensuite créer la colonne que je voulais quelque chose comme ceci:

agedetails['age_range'] = ageRange(agedetails)

MAIS quand j'essaye d'exécuter le premier code pour créer la fonction que j'obtiens:

  File "<ipython-input-124-cf39c7ce66d9>", line 4
    if complete.Age > 1 AND complete.Age < 18 return '2-18'
                          ^
SyntaxError: invalid syntax

De toute évidence, il n'accepte pas le ET - mais je pensais avoir entendu en classe que je pouvais utiliser ET comme ça? Je dois me tromper, mais quelle serait la bonne façon de procéder?

Donc, après avoir obtenu cette erreur, je ne suis même pas sûr que la méthode de transmission d'une trame de données génère également une erreur. Je suppose probablement oui. Dans ce cas - comment pourrais-je faire fonctionner cela aussi?

Je cherche à apprendre la meilleure méthode, mais une partie de la meilleure méthode pour moi est de rester simple même si cela signifie faire les choses en quelques étapes ...

8
kiltannen

Avec Pandas, vous devez éviter les opérations par ligne, car elles impliquent généralement une boucle de niveau Python inefficace. Voici quelques alternatives.

Pandas: pd.cut

Comme le suggère @JonClements, vous pouvez utiliser pd.cut pour cela, l'avantage ici est que votre nouvelle colonne devient catégorique .

Il vous suffit de définir vos limites (y compris np.inf) et les noms de catégorie, puis appliquez pd.cut à la colonne numérique souhaitée.

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 fournit une autre solution propre. L'idée est de définir vos limites et vos noms, de créer un dictionnaire, puis d'appliquer np.digitize à votre colonne Âge. Enfin, utilisez votre dictionnaire pour mapper les noms de vos catégories.

Notez que pour les cas limites, la borne inférieure est utilisée pour le mappage vers un bac.

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))

Résultat

   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+
24
jpp