別のpandas.Seriesに基づいてPandas DataFrameの任意列を置換する最も効率的な方法は?

目的に応じて要検討というか,僕の中でリーズナブルチョイスは(今の所)ない.

What is the fastest way to perform a replace on a column of a Pandas DataFrame based on the index of a separate Series? – StackOverflow

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

ダウンロード3

カテゴリー: 未分類 パーマリンク

別のpandas.Seriesに基づいてPandas DataFrameの任意列を置換する最も効率的な方法は? への2件のフィードバック

  1. ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように

  2. ピンバック: pandas.DataFrame.applyは(時空間効率の観点からは)使用するべきではない – 使用すべき明確な理由がない限りpandas.DataFrame.applyはリーズナブルチョイスになり得ない | 粉末@それは風のように

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください