web-dev-qa-db-ja.com

Pandasのmap、applymap、applyメソッドの違い

基本的な例でこれらのベクトル化法を使用する時期を教えてください。

mapSeriesメソッドで、残りはDataFrameメソッドです。私はapplyapplymapメソッドについて混乱しました。関数をDataFrameに適用する方法が2つあるのはなぜですか?繰り返しますが、使い方を説明する簡単な例は素晴らしいでしょう。

351
marillion

Wes McKinneyの Python for Data Analysisからのストレート book、pg。 132(私はこの本を強く薦める):

もう1つのよくある操作は、1D配列の関数を各列または行に適用することです。 DataFrameのapplyメソッドはまさにこれを行います。

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

最も一般的な配列統計(sumやmeanなど)の多くはDataFrameメソッドなので、applyを使用する必要はありません。

要素別のPython関数も使用できます。フレーム内の各浮動小数点値からフォーマットされた文字列を計算したいとします。これを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

Applymapという名前の理由は、Seriesには要素ごとの関数を適用するためのmapメソッドがあるためです。

In [122]: frame['e'].map(format)
Out[122]: 
Utah       1.28
Ohio      -1.55
Texas      0.20
Oregon    -0.31
Name: e, dtype: object

まとめると、applyはDataFrameの行/列ベースで機能し、applymapはDataFrameの要素単位で機能し、mapはシリーズの要素単位で機能します。

423
jeremiahbuddha

これらの答えにはすばらしい情報がありますが、どのメソッドが配列ワイズと要素ワイズのどちらで機能するかを明確に要約するために私自身を追加します。 jeremiahbuddhaはほとんどこれをしましたが、Series.applyについては言及しませんでした。コメントする担当者がいません。

  • DataFrame.applyは一度に行全体または列全体に作用します。

  • DataFrame.applymapSeries.apply、およびSeries.mapは一度に1つの要素を操作します。

Series.applySeries.mapの機能には多くの重複があります。つまり、どちらの機能もほとんどの場合に機能します。ただし、若干の違いはありますが、そのいくつかはosaの回答で説明されています。

46
MarredCheese

他の答えに加えて、Seriesname__には mapapply もあります。

ApplyはDataFrameをシリーズから作成することができます ;しかし、mapは他のシリーズのすべてのセルにシリーズを配置するだけです。おそらくこれはあなたが望むものではありません。

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

また、「Webサーバーへの接続」などの副作用のある機能を使用している場合は、わかりやすくするためにapplyname__を使用します。

series.apply(download_file_for_every_element) 

Mapname__は、関数だけでなく、辞書または他のシリーズも使用できます。 あなたが 順列を操作したいとしましょう

取る

1 2 3 4 5
2 1 4 5 3

この順列の二乗は、

1 2 3 4 5
1 2 5 3 4

mapname__を使って計算できます。セルフアプリケーションが文書化されているかどうかはわかりませんが、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は、applyは行/列に作用し、applymapは要素ごとに作用すると述べました。しかし、それはあなたがまだ要素ごとの計算にapplyを使うことができるようです....

    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

ちょっと指摘したかったのですが、少し苦労しました。

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

たぶん最も簡単な説明はapplyとapplymapの違いです:

apply 列全体をパラメータとして使用し、結果をこの列に割り当てます。

applymap は別のセル値をパラメータとして取り、結果をこのセルに割り当てます。

注意applyが単一の値を返す場合は、代入後に列ではなくこの値を使用し、最終的には行列ではなく行のみを使用します。

7
Kath

私の理解:

機能の観点からは:

関数に列/行内で比較する必要がある変数がある場合は、applyを使用します。

例:lambda x: x.max()-x.mean().

関数が各要素に適用される場合:

1>列/行が見つかった場合はapplyを使用

2>データフレーム全体に適用する場合は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

mapapplymap 、および apply :の比較

最初の主な違い: _ definition _

  • mapはシリーズのみで定義されています
  • applymapはDataFramesでのみ定義されています
  • applyはBOTHで定義されています

第二の主な違い: 入力引数

  • mapdicts、Series、またはcallableを受け入れます
  • applymapapplyは呼び出し可能オブジェクトのみを受け入れます

3番目の大きな違い: _動作_

  • mapはSeriesの場合はelementwiseです
  • applymapはDataFrameの場合はelementwiseです。
  • applyも要素ごとに機能しますが、より複雑な操作や集計に適しています。動作と戻り値は関数によって異なります。

4番目の大きな違い(最も重要なもの): ユースケース

  • mapはあるドメインから別のドメインへ値をマッピングするためのもので、パフォーマンスのために最適化されています。
  • applymapは複数の行/列にわたる要素ごとの変換に適しています
  • applyはベクトル化できない関数を適用するためのものです

要約する

enter image description here 

脚注

  1. mapは辞書/シリーズに渡されると、その辞書/シリーズのキーに基づいて要素をマップします。欠落している値は、出力にNaNとして記録されます。
  2. 最近のバージョンのapplymapはいくつかの操作に最適化されています。場合によっては、applymapapplyよりわずかに速いことがわかります。私の提案は、それらを両方ともテストして、うまくいくものなら何でも使うことです。

  3. mapは要素単位のマッピングと変換に最適化されています。辞書またはシリーズを含む操作は、パンダがより良いパフォーマンスのためにより速いコードパスを使うことを可能にします。

  4. Series.applyは集約演算のスカラを返し、そうでなければSeriesを返します。 DataFrame.applyについても同様です。 applymeanなどの特定のNumPy関数で呼び出された場合、sumもファストパスを持ちます。
1
cs95

FOMO:

次の例は、 apply および applymapDataFrameに適用したものです。

map functionはSeriesにのみ適用できます。 DataFrameに map を適用することはできません。

覚えておくべきことは、 apply 何でもできる applymap ができますが、 apply eXtra オプションを持っているということです。

Xファクターのオプションは次のとおりです。axisおよびresult_typeここで、result_typeは、axis=1(列用)の場合にのみ機能します。

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
0
prosti