J'ai un cadre de données de pandas qui ressemble à ceci:
portion used
0 1 1.0
1 2 0.3
2 3 0.0
3 4 0.8
J'aimerais créer une nouvelle colonne basée sur la colonne used
, de sorte que la df
ressemble à ceci:
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
alert
basée surused
est 1.0
, alert
devrait être Full
.used
est 0.0
, alert
devrait être Empty
.alert
devrait être Partial
.Quelle est la meilleure façon de faire ça?
Vous pouvez définir une fonction qui renvoie vos différents états "Complet", "Partiel", "Vide", etc., puis utilisez df.apply
pour appliquer la fonction à chaque ligne. Notez que vous devez passer le mot clé argument axis=1
pour vous assurer qu'il applique la fonction aux lignes.
import pandas as pd
def alert(c):
if c['used'] == 1.0:
return 'Full'
Elif c['used'] == 0.0:
return 'Empty'
Elif 0.0 < c['used'] < 1.0:
return 'Partial'
else:
return 'Undefined'
df = pd.DataFrame(data={'portion':[1, 2, 3, 4], 'used':[1.0, 0.3, 0.0, 0.8]})
df['alert'] = df.apply(alert, axis=1)
# portion used alert
# 0 1 1.0 Full
# 1 2 0.3 Partial
# 2 3 0.0 Empty
# 3 4 0.8 Partial
Sinon, vous pouvez faire:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'portion':np.arange(10000), 'used':np.random.Rand(10000)})
%%timeit
df.loc[df['used'] == 1.0, 'alert'] = 'Full'
df.loc[df['used'] == 0.0, 'alert'] = 'Empty'
df.loc[(df['used'] >0.0) & (df['used'] < 1.0), 'alert'] = 'Partial'
Ce qui donne la même sortie mais est environ 100 fois plus rapide sur 10 000 lignes:
100 loops, best of 3: 2.91 ms per loop
Puis en appliquant:
%timeit df['alert'] = df.apply(alert, axis=1)
1 loops, best of 3: 287 ms per loop
Je suppose que le choix dépend de la taille de votre base de données.
Utilisez np.where
, est généralement rapide
In [845]: df['alert'] = np.where(df.used == 1, 'Full',
np.where(df.used == 0, 'Empty', 'Partial'))
In [846]: df
Out[846]:
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
Les horaires
In [848]: df.shape
Out[848]: (100000, 3)
In [849]: %timeit df['alert'] = np.where(df.used == 1, 'Full', np.where(df.used == 0, 'Empty', 'Partial'))
100 loops, best of 3: 6.17 ms per loop
In [850]: %%timeit
...: df.loc[df['used'] == 1.0, 'alert'] = 'Full'
...: df.loc[df['used'] == 0.0, 'alert'] = 'Empty'
...: df.loc[(df['used'] >0.0) & (df['used'] < 1.0), 'alert'] = 'Partial'
...:
10 loops, best of 3: 21.9 ms per loop
In [851]: %timeit df['alert'] = df.apply(alert, axis=1)
1 loop, best of 3: 2.79 s per loop
df ['TaxStatus'] = np.where (df.Public == 1, True, np.where (df.Public == 2, False))
Cela semblerait fonctionner, sauf pour ValueError: les deux ou aucun des x et y devraient être donnés
Je ne peux pas commenter, donc en formulant une nouvelle réponse: En améliorant l'approche de Ffisegydd, vous pouvez utiliser un dictionnaire et la méthode dict.get()
pour rendre la fonction à transmettre à .apply()
plus facile à gérer:
import pandas as pd
def alert(c):
mapping = {1.0: 'Full', 0.0: 'Empty'}
return mapping.get(c['used'], 'Partial')
df = pd.DataFrame(data={'portion':[1, 2, 3, 4], 'used':[1.0, 0.3, 0.0, 0.8]})
df['alert'] = df.apply(alert, axis=1)
Selon le cas d'utilisation, vous souhaiterez peut-être également définir le dict en dehors de la définition de la fonction.