目的に応じて要検討というか,僕の中でリーズナブルチョイスは(今の所)ない.
1列の処理であれば,pandas.Series.mapがリーズナブルチョイス.ただ,複数列になると,これは,置換したい列の数や辞書の大きさ(ラベル数)で一概に云えないのではないかなと.今の場合,列数が少ないので,ピュアにループする回数が少ないから,回答の方法が最も効率的だが,列数が増えれば,pandas.DataFrame.mapによるベネフィットよりもピュアにループするコストの方が大きくなるので,結果は変わってくる筈.そういった諸々を考えて,フィッティングする位なら,そういう意味では,どの方法も大した差は無いので,データが数値であればnumpyに置き換え,文字列等を含む混合データであれば,pandas.DataFrame.replaceがリーズナブルだとも考えられるし,かといって,置き換えられる値が全体の何%かでも結果は変わってくるので,例えば多い場合はreplaceは物凄く遅かったりするので,ループを回してmapを適用する方が良いかも知れないが,昔の様に無条件にpandas.Series.mapの方が良いとは必ずしも云えないんじゃないかなと(ましてやデータフレーム全体の処理を考えた時には).
(また,大元がファイルの場合は文字列のままreモジュールで処理する方が遥かに効率的)
import io import pandas as pd import perfplot def func(df): for c in ['idxA', 'idxB']: df[c] = df[c].map(labels) return df strings = """ idxA idxB var2 0 0 1 2.0 1 0 2 3.0 2 2 4 2.0 3 2 1 1.0""" df = pd.read_csv(io.StringIO(strings), sep='\s+') print(df) labels = pd.Series(['A', 'B', 'C', 'D', 'E']) print(labels) label_dict = labels.to_dict() print(label_dict) print(df.assign(**df[['idxA', 'idxB']].apply(lambda x: x.map(labels)))) %timeit df.assign(**df[['idxA', 'idxB']].apply(lambda x: x.map(labels))) print(df.assign(**df[['idxA', 'idxB']].replace(labels))) %timeit df.assign(**df[['idxA', 'idxB']].replace(labels)) print(func(df)) %timeit func(df) perfplot.show( setup=lambda N: pd.concat([df]*N, ignore_index=True), kernels=[ lambda df: df.assign(**df[['idxA', 'idxB']].apply(lambda x: x.map(labels))), lambda df: df.assign(**df[['idxA', 'idxB']].replace(labels)), lambda df: func(df) ], labels=['apply(map)', 'pandas.DataFrame.replace', 'inplace for loop'], n_range=[2**k for k in range(1, 23)], xlabel='N', logx=True, logy=True, equality_check=False )
idxA idxB var2 0 0 1 2.0 1 0 2 3.0 2 2 4 2.0 3 2 1 1.0 0 A 1 B 2 C 3 D 4 E dtype: object {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E'} idxA idxB var2 0 A B 2.0 1 A C 3.0 2 C E 2.0 3 C B 1.0 100 loops, best of 3: 2.8 ms per loop idxA idxB var2 0 A B 2.0 1 A C 3.0 2 C E 2.0 3 C B 1.0 100 loops, best of 3: 2.14 ms per loop idxA idxB var2 0 A B 2.0 1 A C 3.0 2 C E 2.0 3 C B 1.0 1000 loops, best of 3: 1.01 ms per loop
ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように
ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように