Pandas DataFrame
のインデックスに関数を適用する最良の方法は何ですか?現在、この冗長アプローチを使用しています:
pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})
ここで、Date
はインデックスの名前、foo
は適用する関数の名前です。
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()
_
これにより、シリーズではなく、インデックスオブジェクトが生成されます。
関数 "foo"をインデックスに適用して、現在のDataFrameに列を作成すると仮定します。あなたは書くことができます...
df['Month'] = df.index.map(foo)
単独でシリーズを生成するには、代わりに次のようにします...
pd.Series({x: foo(x) for x in foo.index})
多くの回答がインデックスを配列として返していますが、これはインデックス名などに関する情報を失います(ただし、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%の時間で機能します。