web-dev-qa-db-fra.com

Différence entre les méthodes map, applymap et apply dans les pandas

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!

361
marillion

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.

431
jeremiahbuddha

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.

48
MarredCheese

En ajoutant aux autres réponses, dans Seriesname__, 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 applyjuste par souci de clarté.

series.apply(download_file_for_every_element) 

Mappeut 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 mapname__. 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
33
osa

@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
19
user2921752

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

cela ne modifie pas le dataframe lui-même, doit être réaffecté

df = df.applymap(f)
df.describe()
9
muon

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.

8
Kath

Comparaison map , applymap et apply : Le contexte est important

Première différence majeure: DÉFINITION

  • map est défini sur la série SEULEMENT
  • applymap est défini sur les DataFrames UNIQUEMENT
  • apply est défini sur les deux

Deuxième différence majeure: ARGUMENT DE SAISIE

  • map accepte dicts, Series ou appelable
  • applymap et apply acceptent uniquement les callables

Troisième différence majeure: COMPORTEMENT

  • map est élémentaire pour la série
  • applymap est élémentaire pour les DataFrames
  • apply 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/colonnes
  • apply sert à appliquer toute fonction qui ne peut pas être vectorisée

Résumant

enter image description here

Notes de bas de page

  1. 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.
  2. applymap dans les versions plus récentes a été optimisé pour certaines opérations. applymap sera légèrement plus rapide que apply dans certains cas. Ma suggestion est de les tester tous les deux et d’utiliser tout ce qui fonctionne mieux.

  3. 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.

  4. Series.apply renvoie un scalaire pour l'agrégation des opérations, sinon, Series. De même pour DataFrame.apply. Notez que apply possède également des raccourcis lorsqu'il est appelé avec certaines fonctions NumPy telles que mean, sum, etc.
4
cs95

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)
2
Vicky Miao

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_typeresult_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 .

0
prosti