applymapとかの高階関数をいろいろ試してみる
前回の記事でChatGPTにapplymapを使ってデータフレームに特定の文字列を含む列の抽出方法を教えてもらったので、もう少しいろいろ試してみようと思います。
ちなみにapplymapのように引数に関数を渡したり、関数を戻り値とする関数を高階関数というそうです。
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
このデータフレームをapplymap関数を使って触っていこうと思います。
全ての要素を対象に「バナナ」を「ばなな」に置き換えてみようと思います。
df.applymap(lambda x: 'ばなな' if str(x)=='バナナ' else x)
仕入先 果物 価格
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
「バナナ」が「ばなな」に置きかわりました。
lambda式の 引数x ですが個人的には最初これがなんなのかよくわかりませんでした。勝手に名付けたものなのでxだろうがyだろうがなんでもいいのですが、これはdfの各要素にあたります。
なのでdfの全ての要素に対して、バナナという文字列であれば、ばななに置き換えるということになります。
ちなみにstr(x)としたのは、要素にいろいろな型があるとエラーを起こすことがあるようなので、全て文字列とした上での条件式としました。この場合は価格はint型だと思うのですが、if x=='バナナ' ~ としてもエラーを起こしませんでした。なのでどういうときにエラーを起こすかはよくわかりません。
次に果物のカラムを全て「メロン」に置き換えようと思います。
df['果物'].applymap(lambda x: 'メロン')
こう書きたいところですが、
AttributeError: 'Series' object has no attribute 'applymap'
こういうエラーを返します。
pandasのDataframeの特定のカラムを抽出したものはSeriesになるようです。そしてSeriesはapplymap関数を使えないようです。
では何を使うか。map関数を使います。
df['果物'].map(lambda x: 'メロン')
0 メロン
1 メロン
2 メロン
3 メロン
4 メロン
5 メロン
6 メロン
7 メロン
すべてメロンに置き換わりました。
次に価格が150より大きい列のみを抽出してみようと思います。
df['価格'].map(lambda x: x>150)
0 False
1 True
2 False
3 True
4 True
5 True
6 True
7 False
df['価格']はSeriesなので今回もmap関数を使います。
結果はbool型でかえってきます。
Trueの行のみ抽出してみます。
df[df['価格'].map(lambda x: x>150)]
仕入先 果物 価格
1 商店C バナナ 200
3 商店A いちご 600
4 商店C ぶどう 250
5 商店A みかん 300
6 商店A いちご 200
df[ ]で囲ってやるとTrueの行のみ表示させることができました。
最後に「A」という文字列を含む列のみ抽出してみようと思います。
今回はデータフレーム全体が対象になるのでapplymap関数を使用します。
df.applymap(lambda x: 'A' in str(x))
仕入先 果物 価格
0 True False False
1 False False False
2 False True False
3 True False False
4 False False False
5 True False False
6 True False False
7 False False False
各要素にTrue、Falseが返ってきます。
ただしこれでは各行にTrueとFalseが混在しているので先ほどと同じやり方でTrueのみ抽出するということはできなさそうです。
試しにやってみます。
df[df.applymap(lambda x: 'A' in str(x))]
仕入先 果物 価格
0 商店A NaN NaN
1 NaN NaN NaN
2 NaN みかんA NaN
3 商店A NaN NaN
4 NaN NaN NaN
5 商店A NaN NaN
6 商店A NaN NaN
7 NaN NaN NaN
Trueの要素のみ元のデータが表示されます。
今回抽出したい行は文字列「A」が含まれている行なので、それぞれの行にTrueが1つでもあるものが対象となります。
そこで登場するのがany()です。
早速使ってみます。
df.applymap(lambda x: 'A' in str(x)).any(axis=1)
0 True
1 False
2 True
3 True
4 False
5 True
6 True
7 False
各カラムに1つでもTrueがあるものがTrueとなりました。
any()関数はPythonの組み込み関数の一つで、イテラブル(リスト、タプル、セット、辞書など)の中に少なくとも1つの真(True)の要素が含まれているかどうかを判定するために使用されます。
引数のaxis=0は行方向に対して、axis=1は列方向に対してTrueが1つ以上あるかを判定します。
df[df.applymap(lambda x: 'A' in str(x)).any(axis=1)]
仕入先 果物 価格
0 商店A りんご 130
2 商店C みかんA 70
3 商店A いちご 600
5 商店A みかん 300
6 商店A いちご 200
これで文字列「A」が含まれる行のみ抽出できました。
今回はapplymapとmapについて試してみましたがこれとよく似た動きをするものでapplyというものがあります。
これについても次回試してみようと思います。
この記事が気に入ったらサポートをしてみませんか?