次のような構造のデータフレームがあります。
First A B
Second bar baz foo bar baz foo
Third cat dog cat dog cat dog cat dog cat dog cat dog
0 3 8 7 7 4 7 5 3 2 2 6 2
1 8 6 5 7 8 7 1 8 6 0 3 9
2 9 2 2 9 7 3 1 8 4 1 0 8
3 3 6 0 6 3 2 2 6 2 4 6 9
4 7 6 4 3 1 5 0 4 8 4 8 1
したがって、3 つの列レベルがあります。第 2 レベルに新しい列を追加して、第 3 レベルごとに計算を実行したいと考えています。たとえば、'new' = 'foo' + 'bar' です。したがって、結果のデータフレームは次のようになります。
First A B
Second bar baz foo new bar baz foo new
Third cat dog cat dog cat dog cat dog cat dog cat dog cat dog cat dog
0 3 8 7 7 4 7 7 15 5 3 2 2 6 2 11 5
1 8 6 5 7 8 7 16 13 1 8 6 0 3 9 4 17
2 9 2 2 9 7 3 16 5 1 8 4 1 0 8 1 16
3 3 6 0 6 3 2 6 8 2 6 2 4 6 9 8 15
4 7 6 4 3 1 5 8 11 0 4 8 4 8 1 8 5
この投稿の最後にリストされている回避策を見つけましたが、「パンダスタイル」ではなく、エラーが発生しやすくなっています。グループの適用または変換機能は正しい方法のように思えますが、何時間も試してみてもまだ成功しません。私は正しい方法が次のようなものであるべきだと考えました:
def func(data):
fi = data.columns[0][0]
th = data.columns[0][2]
data[(fi,'new',th)] = data[(fi,'foo',th)] + data[(fi,'bar',th)]
print data
return data
print grouped.apply(func)
新しい列は関数内に適切に追加されますが、返されません。「新しい」列が df に既に存在する場合、transform で同じ関数を使用すると機能しますが、「オンザフライ」またはグループ化の前に特定のレベルで新しい列を追加するにはどうすればよいですか?
サンプル df を生成するコードは次のとおりです。
import pandas, itertools
first = ['A','B']
second = ['foo','bar','baz']
third = ['dog', 'cat']
tuples = []
for tup in itertools.product(first, second, third):
tuples.append(tup)
columns = pandas.MultiIndex.from_tuples(tuples, names=['First','Second','Third'])
data = np.random.randint(0,10,(5, 12))
df = pandas.DataFrame(data, columns=columns)
そして私の回避策:
dfnew = None
grouped = df.groupby(by=None, level=[0,2], axis=1)
for name, group in grouped:
newparam = group.xs('foo', axis=1, level=1) + group.xs('bar', axis=1, level=1)
dftmp = group.join(pandas.DataFrame(np.array(newparam), columns=pandas.MultiIndex.from_tuples([(group.columns[0][0], 'new', group.columns[0][2])], names=['First','Second', 'Third'])))
if dfnew is None:
dfnew = dftmp
else:
dfnew = pandas.concat([dfnew, dftmp], axis=1)
print dfnew.sort_index(axis=1)
これは機能しますが、グループごとに新しいデータフレームを作成し、「手動で」レベルを割り当てることは本当に悪い習慣です。
それで、これを行う適切な方法は何ですか?同様の質問を扱う投稿をいくつか見つけましたが、これらはすべて 1 レベルの列しかなく、まさに私が苦労していることです。