Pouvez-vous me dire quand utiliser ces méthodes de vectorisation avec des exemples simples?
Je vois que map
est une méthode Series
alors que le reste sont des méthodes DataFrame
. Je me suis confondu avec les méthodes apply
et applymap
cependant. Pourquoi avons-nous deux méthodes pour appliquer une fonction à un DataFrame? Encore une fois, des exemples simples qui illustrent l'utilisation seraient formidables!
Directement de Wes McKinney's Python pour l'analyse de données livre, pg. 132 (j'ai fortement recommandé ce livre):
Une autre opération fréquente consiste à appliquer une fonction sur des tableaux 1D à chaque colonne ou ligne. La méthode apply de DataFrame fait exactement cela:
In [116]: frame = DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
In [117]: frame
Out[117]:
b d e
Utah -0.029638 1.081563 1.280300
Ohio 0.647747 0.831136 -1.549481
Texas 0.513416 -0.884417 0.195343
Oregon -0.485454 -0.477388 -0.309548
In [118]: f = lambda x: x.max() - x.min()
In [119]: frame.apply(f)
Out[119]:
b 1.133201
d 1.965980
e 2.829781
dtype: float64
La plupart des statistiques de tableau les plus courantes (telles que sum et mean) sont des méthodes DataFrame. Il n'est donc pas nécessaire d'utiliser apply.
Des fonctions Python par élément peuvent également être utilisées. Supposons que vous souhaitiez calculer une chaîne mise en forme à partir de chaque valeur en virgule flottante du cadre. Vous pouvez le faire avec applymap:
In [120]: format = lambda x: '%.2f' % x
In [121]: frame.applymap(format)
Out[121]:
b d e
Utah -0.03 1.08 1.28
Ohio 0.65 0.83 -1.55
Texas 0.51 -0.88 0.20
Oregon -0.49 -0.48 -0.31
La raison pour le nom applymap est que Series dispose d'une méthode de carte pour appliquer une fonction élément par élément:
In [122]: frame['e'].map(format)
Out[122]:
Utah 1.28
Ohio -1.55
Texas 0.20
Oregon -0.31
Name: e, dtype: object
En résumé, apply
fonctionne sur la base ligne/colonne d'un DataFrame, applymap
fonctionne élément par élément sur un DataFrame et map
fonctionne élément par élément sur une série.
Il y a d'excellentes informations dans ces réponses, mais j'ajoute les miennes pour résumer clairement les méthodes qui fonctionnent par rang ou par élément. jeremiahbuddha l'a fait la plupart du temps mais n'a pas mentionné Series.apply. Je n'ai pas le représentant à commenter.
DataFrame.apply
opère sur des lignes entières ou des colonnes à la fois.
DataFrame.applymap
, Series.apply
et Series.map
fonctionnent sur un élément à la fois.
Il existe de nombreux chevauchements entre les capacités de Series.apply
et Series.map
, ce qui signifie que l’un ou l’autre fonctionnera dans la plupart des cas. Ils ont cependant quelques légères différences, dont certaines ont été discutées dans la réponse d'OSA.
En ajoutant aux autres réponses, dans Series
name__, il y a aussi map et apply .
Appliquer peut créer un DataFrame à partir d'une série ; Cependant, map mettra simplement une série dans chaque cellule d'une autre série, ce qui n'est probablement pas ce que vous voulez.
In [40]: p=pd.Series([1,2,3])
In [41]: p
Out[31]:
0 1
1 2
2 3
dtype: int64
In [42]: p.apply(lambda x: pd.Series([x, x]))
Out[42]:
0 1
0 1 1
1 2 2
2 3 3
In [43]: p.map(lambda x: pd.Series([x, x]))
Out[43]:
0 0 1
1 1
dtype: int64
1 0 2
1 2
dtype: int64
2 0 3
1 3
dtype: int64
dtype: object
De plus, si j'avais une fonction avec des effets secondaires, telle que "se connecter à un serveur Web", j'utiliserais probablement apply
juste par souci de clarté.
series.apply(download_file_for_every_element)
Map
peut utiliser non seulement une fonction, mais également un dictionnaire ou une autre série. Supposons que vous souhaitiez manipuler permutations .
Prendre
1 2 3 4 5
2 1 4 5 3
Le carré de cette permutation est
1 2 3 4 5
1 2 5 3 4
Vous pouvez le calculer en utilisant map
name__. Pas sûr que l'auto-application soit documentée, mais cela fonctionne dans 0.15.1
.
In [39]: p=pd.Series([1,0,3,4,2])
In [40]: p.map(p)
Out[40]:
0 0
1 1
2 4
3 2
4 3
dtype: int64
@jeremiahbuddha a mentionné que apply fonctionne sur la ligne/les colonnes, tandis que applymap fonctionne au niveau des éléments. Mais il semble que vous pouvez toujours utiliser appliquer pour le calcul élément par élément ....
frame.apply(np.sqrt)
Out[102]:
b d e
Utah NaN 1.435159 NaN
Ohio 1.098164 0.510594 0.729748
Texas NaN 0.456436 0.697337
Oregon 0.359079 NaN NaN
frame.applymap(np.sqrt)
Out[103]:
b d e
Utah NaN 1.435159 NaN
Ohio 1.098164 0.510594 0.729748
Texas NaN 0.456436 0.697337
Oregon 0.359079 NaN NaN
Je voulais juste souligner, comme je me suis battu avec cela pendant un peu
def f(x):
if x < 0:
x = 0
Elif x > 100000:
x = 100000
return x
df.applymap(f)
df.describe()
df = df.applymap(f)
df.describe()
Explication probablement la plus simple de la différence entre apply et applymap:
apply prend la colonne entière en paramètre, puis affecte le résultat à cette colonne
applymap prend la valeur de cellule séparée en tant que paramètre et assigne le résultat à cette cellule.
NB: Si apply renvoie la valeur unique, vous aurez cette valeur au lieu de la colonne après l'affectation et vous aurez éventuellement juste une ligne au lieu de la matrice.
map
, applymap
et ap
ply
: Le contexte est importantPremière différence majeure: DÉFINITION
map
est défini sur la série SEULEMENTapplymap
est défini sur les DataFrames UNIQUEMENTapply
est défini sur les deuxDeuxième différence majeure: ARGUMENT DE SAISIE
map
accepte dict
s, Series
ou appelableapplymap
et apply
acceptent uniquement les callablesTroisième différence majeure: COMPORTEMENT
map
est élémentaire pour la sérieapplymap
est élémentaire pour les DataFramesapply
fonctionne également par élément, mais convient à des opérations et à des agrégations plus complexes. Le comportement et la valeur de retour dépendent de la fonction.Quatrième différence majeure (la plus importante): USE CASE
map
est destiné à mapper des valeurs d'un domaine à un autre, il est donc optimisé pour la performance.applymap
convient aux transformations élémentaires sur plusieurs lignes/colonnesapply
sert à appliquer toute fonction qui ne peut pas être vectoriséeNotes de bas de page
map
une fois passé un dictionnaire/une série mappera les éléments en fonction des clés de ce dictionnaire/cette série. Les valeurs manquantes seront enregistrées en tant que NaN dans la sortie.
applymap
dans les versions plus récentes a été optimisé pour certaines opérations.applymap
sera légèrement plus rapide queapply
dans certains cas. Ma suggestion est de les tester tous les deux et d’utiliser tout ce qui fonctionne mieux.
map
est optimisé pour les mappages et la transformation élément par élément. Les opérations impliquant des dictionnaires ou des séries permettront aux pandas d’utiliser des chemins de code plus rapides pour de meilleures performances.Series.apply
renvoie un scalaire pour l'agrégation des opérations, sinon, Series. De même pourDataFrame.apply
. Notez queapply
possède également des raccourcis lorsqu'il est appelé avec certaines fonctions NumPy telles quemean
,sum
, etc.
Ma compréhension:
Du point de vue de la fonction:
Si la fonction comporte des variables devant être comparées dans une colonne/ligne, utilisez apply
.
exemple: lambda x: x.max()-x.mean()
.
Si la fonction doit être appliquée à chaque élément:
1> Si une colonne/ligne est localisée, utilisez apply
2> Si vous appliquez à l'intégralité de la structure de données, utilisez applymap
majority = lambda x : x > 17
df2['legal_drinker'] = df2['age'].apply(majority)
def times10(x):
if type(x) is int:
x *= 10
return x
df2.applymap(times10)
FOMO:
L'exemple suivant montre apply
et applymap
appliqué à un DataFrame
.
map
est une fonction que vous appliquez uniquement à la série. Vous ne pouvez pas appliquer map
sur DataFrame.
La chose à retenir est que apply
peut faire n'importe quoi applymap
peut, mais apply
a les options eXtra .
Les options de facteur X sont: axis
et result_type
où result_type
ne fonctionne que lorsque axis=1
(pour les colonnes).
df = DataFrame(1, columns=list('abc'),
index=list('1234'))
print(df)
f = lambda x: np.log(x)
print(df.applymap(f)) # apply to the whole dataframe
print(np.log(df)) # applied to the whole dataframe
print(df.applymap(np.sum)) # reducing can be applied for rows only
# apply can take different options (vs. applymap cannot)
print(df.apply(f)) # same as applymap
print(df.apply(sum, axis=1)) # reducing example
print(df.apply(np.log, axis=1)) # cannot reduce
print(df.apply(lambda x: [1, 2, 3], axis=1, result_type='expand')) # expand result
En tant que note, la fonction Series map
ne doit pas être confondue avec la fonction Python map
.
Le premier est appliqué à la série pour mapper les valeurs et le second à chaque élément d'un itérable.
Enfin, ne confondez pas la méthode dataframe apply
avec la méthode groupby apply
.