web-dev-qa-db-fra.com

Utilisation de Apply dans Pandas Fonctions Lambda avec plusieurs instructions if

J'essaie d'inférer une classification en fonction de la taille d'une personne dans une trame de données comme celle-ci:

      Size
1     80000
2     8000000
3     8000000000
...

Je veux que ça ressemble à ceci:

      Size        Classification
1     80000       <1m
2     8000000     1-10m
3     8000000000  >1bi
...

Je comprends que le processus idéal serait d'appliquer une fonction lambda comme celle-ci:

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else "1-10m" if 1000000<x<10000000 else ...)

J'ai vérifié quelques articles concernant plusieurs ifs dans une fonction lambda, voici un exemple de lien , mais ce synthax ne fonctionne pas pour moi pour une raison quelconque dans une instruction multiple ifs, mais il fonctionnait dans un seul si condition.

J'ai donc essayé cette solution "très élégante":

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "1-10m" if 1000000 < x < 10000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "10-50m" if 10000000 < x < 50000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "50-100m" if 50000000 < x < 100000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "100-500m" if 100000000 < x < 500000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "500m-1bi" if 500000000 < x < 1000000000 else pass)
df['Classification']=df['Size'].apply(lambda x: ">1bi" if 1000000000 < x else pass)

Fonctionne que "passer" ne semble pas s'appliquer également aux fonctions lambda:

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
SyntaxError: invalid syntax

Des suggestions sur le synthax correct pour une instruction multiple if à l'intérieur d'une fonction lambda dans une méthode apply dans Pandas? Les solutions multilignes ou monolignes fonctionnent pour moi.

4
abutremutante

Voici un petit exemple sur lequel vous pouvez vous appuyer:

Fondamentalement, lambda x: x.. est la ligne courte d'une fonction. Ce qui s'applique vraiment, c'est une fonction que vous pouvez facilement recréer.

import pandas as pd

# Recreate the dataframe
data = dict(Size=[80000,8000000,800000000])
df = pd.DataFrame(data)

# Create a function that returns desired values
# You only need to check upper bound as the next Elif-statement will catch the value
def func(x):
    if x < 1e6:
        return "<1m"
    Elif x < 1e7:
        return "1-10m"
    Elif x < 5e7:
        return "10-50m"
    else:
        return 'N/A'
    # Add Elif statements....

df['Classification'] = df['Size'].apply(func)

print(df)

Retour:

        Size Classification
0      80000            <1m
1    8000000          1-10m
2  800000000            N/A
6
Anton vBR

Vous pouvez utiliser pd.cut fonction :

bins = [0, 1000000, 10000000, 50000000, ...]
labels = ['<1m','1-10m','10-50m', ...]

df['Classification'] = pd.cut(df['Size'], bins=bins, labels=labels)
5
MaxU

Utilisation de searchsorted de Numpy

labels = np.array(['<1m', '1-10m', '10-50m', '>50m'])
bins = np.array([1E6, 1E7, 5E7])

# Using assign is my preference as it produces a copy of df with new column
df.assign(Classification=labels[bins.searchsorted(df['Size'].values)])

Si vous vouliez produire une nouvelle colonne dans une trame de données existante

df['Classification'] = labels[bins.searchsorted(df['Size'].values)]

Quelques explications

De Documents: np.searchsorted

Trouvez les indices où les éléments doivent être insérés pour maintenir l'ordre.

Trouvez les indices dans un tableau trié tel que, si les éléments correspondants dans v étaient insérés avant les indices, l'ordre de a serait conservé.

Le tableau labels a une longueur supérieure à celle de bins d'une unité. Parce que lorsque quelque chose est supérieur à la valeur maximale dans bins, searchsorted renvoie un -1. Lorsque nous coupons labels, cela prend la dernière étiquette.

2
piRSquared