を使用した別の回答from_tuples()
。これは、この前の答えを一般化します。
key = "Foo"
name = "First"
# If df.index.nlevels > 1:
df.index = pd.MultiIndex.from_tuples(((key, *item) for item in df.index),
names=[name]+df.index.names)
# If df.index.nlevels == 1:
# df.index = pd.MultiIndex.from_tuples(((key, item) for item in df.index),
# names=[name]+df.index.names)
私はこのアプローチが好きです。
- インデックスを変更するだけです(本文の不要なコピーアクションはありません)
- 両方の軸(行と列のインデックス)で機能します
- それでもワンライナーとして書くことができます
上記を関数でラップすると、行インデックスと列インデックスの切り替え、およびシングルレベルインデックスとマルチレベルインデックスの切り替えが簡単になります。
def prepend_index_level(index, key, name=None):
names = index.names
if index.nlevels==1:
# Sequence of tuples
index = ((item,) for item in index)
tuples_gen = ((key,)+item for item in index)
return pd.MultiIndex.from_tuples(tuples_gen, names=[name]+names)
df.index = prepend_index_level(df.index, key="Foo", name="First")
df.columns = prepend_index_level(df.columns, key="Bar", name="Top")
# Top Bar
# Vals
# First A B
# Foo a1 b1 -0.446066
# b2 -0.248027
# a2 b3 0.522357
# a3 b4 0.404048
最後に、上記は、任意のインデックスレベルでキーを挿入することにより、さらに一般化できます。
def insert_index_level(index, key, name=None, level=0):
def insert_(pos, seq, value):
seq = list(seq)
seq.insert(pos, value)
return tuple(seq)
names = insert_(level, index.names, name)
if index.nlevels==1:
# Sequence of tuples.
index = ((item,) for item in index)
tuples_gen = (insert_(level, item, key) for item in index)
return pd.MultiIndex.from_tuples(tuples_gen, names=names)
df.index = insert_index_level(df.index, key="Foo", name="Last", level=2)
df.columns = insert_index_level(df.columns, key="Bar", name="Top", level=0)
# Top Bar
# Vals
# A B Last
# a1 b1 Foo -0.595949
# b2 Foo -1.621233
# a2 b3 Foo -0.748917
# a3 b4 Foo 2.147814