apply map applymapの使い分けがよくわからぬ
前回はmapとapplymapを試してみましたが、applyというのもどうも同じような動きをするらしい。
試しに前回試したmapやapplymapをapplyに置き換えたところほとんど同じ動きをしました。
使い分けがまったくわかりません。
ということでこの辺りを探っていくことにします。
ChatGPTに聞いてみました。
わかったようなわからないような。
ググってみました。
このサイトがわかりやすい。
基本的には特別な場合を除いてはどちらも同じように使えるようです。
試しにここの1)2)3)のパターンをmapとapplyで確認してみようと思います。
import pandas as pd
data = {
'仕入先': ['商店A', '商店C', '商店C', '商店A', '商店C', '商店A', '商店A', '商店B'],
'果物': ['りんご', 'バナナ', 'みかんA', 'いちご', 'ぶどう', 'みかん', 'いちご', 'すいか'],
'価格': [130, 200, 70, 600, 250, 300, 200, 150]
}
# データフレームを作成
df = pd.DataFrame(data)
# データフレームを表示して確認
print(df)
仕入先 果物 価格
0 商店A りんご 130
1 商店C バナナ 200
2 商店C みかんA 70
3 商店A いちご 600
4 商店C ぶどう 250
5 商店A みかん 300
6 商店A いちご 200
7 商店B すいか 150
前回と同じくこちらのデータを使います。
まずは1)から。
mapはSeriesのみに対応、applyはSeriesでなくても良い。
type(df['価格'])
#
pandas.core.series.Series
まずはdf['価格']がSeriesであることを確認。
mapを試してみます。
df['価格'].map(lambda x: x * 1.1)
#
0 143.0
1 220.0
2 77.0
3 660.0
4 275.0
5 330.0
6 220.0
7 165.0
問題なく動きます。
次にapply。
df['価格'].apply(lambda x: x * 1.1)
#
0 143.0
1 220.0
2 77.0
3 660.0
4 275.0
5 330.0
6 220.0
7 165.0
こちらも問題なし。
カラム2つに対してはどうか。
type(df[['仕入先','果物']])
#
pandas.core.frame.DataFrame
df[['仕入先','果物']].apply(lambda x: True if 'A' in str(x) else False, axis=1)
#
0 True
1 False
2 True
3 True
4 False
5 True
6 True
7 False
applyは問題なし。
ではmapはどうか。
df[['仕入先','果物']].map(lambda x: True if 'A' in str(x) else False, axis=1)
#
AttributeError: 'DataFrame' object has no attribute 'map'
カラム2つに対してはmapは使えないようです。
ちなみにapplymapならどうなるか。
df[['仕入先','果物']].applymap(lambda x: True if 'A' in str(x) else False)
#
仕入先 果物
0 True False
1 False False
2 False True
3 True False
4 False False
5 True False
6 True False
7 False False
個別の要素に対して判定がなされます。
applyの場合は仕入先と果物の文字列を結合させた上で判定を行っているらしく、結合させた文字列に'A'があるかないかを判定しています。
でも要素がintの場合はそれぞれの要素に対して処理を行うようです。
import pandas as pd
data = {
'仕入先': ['商店A', '商店C', '商店C', '商店A', '商店C', '商店A', '商店A', '商店B'],
'価格A': [13430, 2544, 7430, 43434600, 4343250, 34400, 4343200, 443150],
'価格B': [130, 200, 70, 600, 250, 300, 200, 150]
}
# データフレームを作成
df = pd.DataFrame(data)
df[['価格A','価格B']].apply(lambda x: x*2)
#
価格A 価格B
0 26860 260
1 5088 400
2 14860 140
3 86869200 1200
4 8686500 500
5 68800 600
6 8686400 400
7 886300 300
このあたりはなぜなのかよくわからないのでそういうものだということにしておきます。
2)mapは辞書で変換できる。applyではできない。
import pandas as pd
data = {
'仕入先': ['商店A', '商店C', '商店C', '商店A', '商店C', '商店A', '商店A', '商店B'],
'果物': ['りんご', 'バナナ', 'みかん', 'いちご', 'ぶどう', 'みかん', 'いちご', 'すいか'],
}
df = pd.DataFrame(data)
price ={'りんご': '100円', 'バナナ': '150円', 'みかん': '200円', 'いちご': '250円', 'ぶどう': '300円', 'すいか': '400円'}
df['価格'] = df['果物'].map(price)
print(df)
#
仕入先 果物 価格
0 商店A りんご 100円
1 商店C バナナ 150円
2 商店C みかん 200円
3 商店A いちご 250円
4 商店C ぶどう 300円
5 商店A みかん 200円
6 商店A いちご 250円
7 商店B すいか 400円
辞書で変換されたカラムが追加されました。
applyならどうでしょう。
なにかよくわからないエラーが出ました。
もちろんapplymapもだめでした。
3)リストに対してはmapしか使えない。
numbers = [1, 3, 5, 7,9]
list(map(lambda x: x**2, numbers))
mapは問題なく使えます。
applyはどうでしょう。
list(apply(lambda x: x**2, numbers))
#
NameError: name 'apply' is not defined
エラーが出ます。
ここまでいろいろ試してみて、完全に理解したというところまでは到底至っていませんが、こういう場面ではこっちを使うということは多少わかった気がします。
それとは別に、lambda式の使い方がわかったことが1番の収穫だったかも。