2016-12-06 7 views
2

パンダでは明らかに見える計算をしようとしていますが、何回か試してみると正しく実行する方法が見つかりませんでした。パンダの行の値に応じて列を分割します

df = pd.DataFrame([["A", "a", 10.0], 
        ["A", "b", 12.0], 
        ["A", "c", 13.0], 
        ["B", "a", 5.0 ], 
        ["B", "b", 6.0 ], 
        ["B", "c", 7.0 ]]) 

最初の列が2列目にはクラスで、3列目は時間を与える、テスト名です:

私はこのようになりますデータフレームを持っています。各テストは通常​​、3つのクラスを持つテーブルに存在します。各テストのために、私は3つのバー、各クラスに1つのグループを取得するようにするため

sns.factorplot(x="2", y="0", hue="1", data=df, 
       kind="bar") 

これは、このようにそれをプロットするための正しい形式です。

ただし、データフレームを変更して、列2の各値が絶対値ではなく、クラス "a"と比較するようにしたいと考えています。

だから私はこれにそれを変換したいと思います:

df = pd.DataFrame([["A", "a", 1.0], 
        ["A", "b", 1.2], 
        ["A", "c", 1.3], 
        ["B", "a", 1.0], 
        ["B", "b", 1.2], 
        ["B", "c", 1.4]]) 

私は、たとえば、計算を行い、それらが一致するようにインデックスを変更、シリーズを抽出することができる午前:

df_a = df[df[1] == "a"].set_index(0) 
df_b = df[df[1] == "b"].set_index(0) 
df_b["ratio_a"] = df_b[2]/df_a[2] 

しかし、これは確かに非常に非効率的で、私はそれをフォーマットに戻す必要があります。

正しい方法は何ですか?

答えて

2

あなたはまた、いくつかのインデックス・アライメントでこれを行うことができます。

df1 = df.set_index(['test', 'class']) 
df1/df1.xs('a', level='class') 

しかし、変換は、これは良いです

+0

ありがとう、これは正常に動作します! – Dric512

4

あなたは、各グループ内の最初の値を見つけるためにgroupby/transform('first')を使用することができます。

import pandas as pd 
df = pd.DataFrame([["A", "a", 10.0], 
        ["A", "b", 12.0], 
        ["A", "c", 13.0], 
        ["B", "b", 6.0 ], 
        ["B", "a", 5.0 ], 
        ["B", "c", 7.0 ]]) 
df = df.sort_values(by=[0,1]) 
df[2] /= df.groupby(0)[2].transform('first') 

利回り

0 1 2 
0 A a 1.0 
1 A b 1.2 
2 A c 1.3 
3 B a 1.0 
4 B b 1.2 
5 B c 1.4 
+0

優れています。 'df.groupby(0)[2] .transform(lambda x:x/x.iloc [0])'もうまくいくはずですか? – Zero

+0

@JohnGalt: 'transform( 'first')'のような "組み込み"関数はCython化されているので、 'lambda x:x/x.iloc [0]'のような特注関数を使った変換よりもはるかに高速です。しかし、それは同じ結果を生み出すでしょう。 – unutbu

+0

これはよく見えます。 「最初」が正しいラベルであることを保証するために、最初に列1でデータフレームをソートする必要がありますか? – Dric512

関連する問題