2016-12-06 73 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 ]]) 

第一列是一个测试名称,第二列是一个类,第三列给出的时间。每个测试通常在3个班的表中。

这是画出像这样正确的格式:

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

所以每一次测试,我得到一组的3个酒吧,一个为每个类。

但是我想更改数据框,以便第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')'这样的“内置”函数是Cythonized的,所以它们比使用'lambda x:x/x.iloc [0]'等定制函数进行转换要快得多。但是,是的,它会产生相同的结果。 – unutbu

+0

这看起来不错。为了保证“第一个”是正确的标签,我应该首先按第1列对数据框进行排序吗? – Dric512