Pandas.Seriesのデータを作成し、Seaborn.barplotを使って棒グラフ表示しようとしたところ、 NotImplementedError: isna is not defined for MultiIndex というエラーが出てしまい、かなり時間を使ってしまったので備忘録として残します。
用意したSeriesデータ
ランダムなSeries型データを用意し、インデックスは「(女性, 0), (女性, 1), (男性, 0), (男性, 1)」というように設定しました。
0と1の値は、スポーツ経験があるかどうかのフラグとして使用している想定です。
# 使用するデータを用意 (Pandas.Series型)
import pandas as pd
import numpy as np
import seaborn as sns
data = np.random.randint(0, 500, 4)
index = pd.MultiIndex.from_tuples([('女性', 0), ('女性', 1),
('男性', 0), ('男性', 1),]) # マルチインデックス作成
series = pd.Series(data, index=index, name='data')
------------------- 実行結果(サンプル) --------------------------
女性 0 127
1 133
男性 0 315
1 405
Name: data, dtype: int64
エラーになったコード
用意したデータをSeabornを使用して棒グラフ表示しようとして、sns.barplot(series.index, series.values) とコードを書いたところエラーが発生しました。
# 失敗した例
sns.barplot(series.index, series.values)
# sns.barplot(series.keys(), series.values) # 別方法でindexを取得する方法もあるが、こちらも失敗
------------------- 実際に表示されたエラー文章 --------------------------
Output exceeds the size limit. Open the full output data in a text editor
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-178-59d96087e767> in <module>
4 series = pd.Series(data, index=index, name='data')
5
----> 6 sns.barplot(series.index, series.values)
7 sns.barplot(series.keys(), series.values)
8
/opt/anaconda3/lib/python3.8/site-packages/seaborn/_decorators.py in inner_f(*args, **kwargs)
44 )
45 kwargs.update({k: arg for k, arg in zip(sig.parameters, args)})
---> 46 return f(**kwargs)
47 return inner_f
48
/opt/anaconda3/lib/python3.8/site-packages/seaborn/categorical.py in barplot(x, y, hue, data, order, hue_order, estimator, ci, n_boot, units, seed, orient, color, palette, saturation, errcolor, errwidth, capsize, dodge, ax, **kwargs)
3167 ):
3168
-> 3169 plotter = _BarPlotter(x, y, hue, data, order, hue_order,
3170 estimator, ci, n_boot, units, seed,
3171 orient, color, palette, saturation,
/opt/anaconda3/lib/python3.8/site-packages/seaborn/categorical.py in __init__(self, x, y, hue, data, order, hue_order, estimator, ci, n_boot, units, seed, orient, color, palette, saturation, errcolor, errwidth, capsize, dodge)
1582 errwidth, capsize, dodge):
...
--> 153 raise NotImplementedError("isna is not defined for MultiIndex")
154 elif isinstance(obj, type):
155 return False
NotImplementedError: isna is not defined for MultiIndex
別のところでは成功していた書き方だったんですが、この時だけエラーが発生しました。
エラーメッセージに isna と書いてあるので「欠損値関連かな?」と思い調べたのですが、有力な情報が中々見つからず苦労しました…
解決法:to_flat_index() を使いMultiIndex型を変換する
sns.barplotに渡している引数がMultiIndexになっているので、to_flat_index関数を使い、Index型に直してあげるだけで解決できました。
sns.barplot(series.index.to_flat_index(), series.values)
# または下の書き方でもOK
sns.barplot(series.keys().to_flat_index(), series.values)
余談ですが、Series.keys() はインデックスを取得するもので、辞書型というわけではないんですよね。
なので値を取得したい場合はSeries.values と使う必要があるそうです。(valuesは非推奨とのこと)
参考1:Series.keys() – https://pandas.pydata.org/docs/reference/api/pandas.Series.keys.html
参考2:Series.values – https://pandas.pydata.org/docs/reference/api/pandas.Series.values.html
さて、上のコードを実行すると棒グラフを表示することができました。
実際に to_flat_index() をした後のindexの型を見てみると、MultiIndex型からIndex型に変換されているのがわかりますね。これでもう失敗しないですね。
print("1. indexを取得 (MultiIndex型)")
print(series.index)
print("2. index.to_flat_index()を取得 (Index型)")
print(series.index.to_flat_index())
------------------- 実行結果 --------------------------
1. indexを取得 (MultiIndex型)
MultiIndex([('女性', 0),
('女性', 1),
('男性', 0),
('男性', 1)],
)
2. index.to_flat_index()を取得 (Index型)
Index([('女性', 0), ('女性', 1), ('男性', 0), ('男性', 1)], dtype='object')
まとめ
エラー文章で検索しても引っかかるものがなく、リファレンス見てもよく分からなくて焦りました。
同じように悩んでいる人に、少しでもお役に立てれば幸いです。
第1位:フリーランスを始めるならITプロパートナーズ
第2位:キャリアサポートサービス「クラウドテック」
第3位:ライティングからサイト制作まで【Bizseek】
コメントを書く