web-dev-qa-db-ja.com

DataFrameインデックスに関数を適用

Pandas DataFrameのインデックスに関数を適用する最良の方法は何ですか?現在、この冗長アプローチを使用しています:

pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})

ここで、Dateはインデックスの名前、fooは適用する関数の名前です。

58
Alex Rothberg

HYRYのコメントで既に示唆されているように、 Series.map がここに行く方法です。結果のシリーズにインデックスを設定するだけです。

簡単な例:

_df = pd.DataFrame({'d': [1, 2, 3]}, index=['FOO', 'BAR', 'BAZ'])
df
        d
FOO     1
BAR     2
BAZ     3

df.index = df.index.map(str.lower)
df
        d
foo     1
bar     2
baz     3
_

インデックス!=シリーズ

@OPが指摘したとおり。 df.index.map(str.lower)呼び出しは、numpy配列を返します。これは、データフレームインデックスがシリーズではなくnumpy配列に基づいているためです

インデックスをシリーズにする唯一の方法は、そこからシリーズを作成することです。

_pd.Series(df.index.map(str.lower))
_

警告

IndexクラスはStringAccessorMixinのサブクラスになりました。つまり、上記の操作を次のように実行できます。

_df.index.str.lower()
_

これにより、シリーズではなく、インデックスオブジェクトが生成されます。

74
firelynx

関数 "foo"をインデックスに適用して、現在のDataFrameに列を作成すると仮定します。あなたは書くことができます...

df['Month'] = df.index.map(foo)

単独でシリーズを生成するには、代わりに次のようにします...

pd.Series({x: foo(x) for x in foo.index})
7
suraj747

多くの回答がインデックスを配列として返していますが、これはインデックス名などに関する情報を失います(ただし、pd.Series(index.map(myfunc), name=index.name)を実行できます)。また、MultiIndexでは機能しません。

私がこれで作業した方法は、「名前変更」を使用することです。

mix = pd.MultiIndex.from_tuples([[1, 'hi'], [2, 'there'], [3, 'dude']], names=['num', 'name'])
data = np.random.randn(3)
df = pd.Series(data, index=mix)
print(df)
num  name 
1    hi       1.249914
2    there   -0.414358
3    dude     0.987852
dtype: float64

# Define a few dictionaries to denote the mapping
rename_dict = {i: i*100 for i in df.index.get_level_values('num')}
rename_dict.update({i: i+'_yeah!' for i in df.index.get_level_values('name')})
df = df.rename(index=rename_dict)
print(df)
num  name       
100  hi_yeah!       1.249914
200  there_yeah!   -0.414358
300  dude_yeah!     0.987852
dtype: float64

これの唯一の秘isは、インデックスに異なるマルチインデックスレベルのユニークなラベルが必要なことですが、それを回避する方法を私よりも賢い人が知っているかもしれません。私の目的では、これは95%の時間で機能します。

3
choldgraf