熊猫透视表
我的熊猫数据框如下:熊猫透视表
df = pd.DataFrame({"PAR NAME":['abc','def','def','def','abc'], "value":[1,2,3,4,5],"DESTCD":['E','N','E','E','S']})
我需要转动自由度的PAR名称,并找出它的价值%年龄来自哪里DESTCD是“E”的地方。像这样的东西(这显然没有工作!)
df.pivot_table(index="PAR NAME",values=["value"],aggfunc={'value':lambda x: (x.sum() if x["DESTCD"]=="E")*100.0/x.sum()})
我目前做这通过增加一个条件列,然后总结其与支点“价值”一起,然后分,但我的数据库是巨大的(1GB +)而且必须有一个更简单的方法。
编辑:预期输出 ABC 16.67(因为ABC以及E是1出总ABC它是6) DEF 77.78(因为DEF和E是7出的总共9个DEF的);
(注:请不要推荐切片多dataframes提到我的数据是巨大的,效率很关键,:))
我试图解决这个问题没有明确提到 'E' 所以它推广到任何字母开头。输出是一个数据框,然后您可以在E上索引以获得答案。我简单地分别进行了聚合,然后使用了高效的连接方法。
df = pd.DataFrame({"PAR NAME":['abc','def','def','def','abc'], "value":[1,2,3,4,5],"DESTCD":['E','N','E','E','S']})
# First groupby 'DESTCD' and 'PAR NAME'
gb = df.groupby(['DESTCD', 'PAR NAME'], as_index=False).sum()
print(gb)
DESTCD PAR NAME value
0 E abc 1
1 E def 7
2 N def 2
3 S abc 5
gb_parname = gb.groupby(['PAR NAME']).sum()
out = gb.join(gb_parname, on='PAR NAME', rsuffix='Total')
print(out)
DESTCD PAR NAME value valueTotal
0 E abc 1 6
1 E def 7 9
2 N def 2 9
3 S abc 5 6
out.loc[:, 'derived']= out.apply(lambda df: df.value/df.valueTotal, axis=1)
print(out)
DESTCD PAR NAME value valueTotal derived
0 E abc 1 6 0.166667
1 E def 7 9 0.777778
2 N def 2 9 0.222222
3 S abc 5 6 0.833333
这也是一个比较有效的操作
%%timeit
gb = df.groupby(['DESTCD', 'PAR NAME'], as_index=False).sum()
gb_parname = gb.groupby(['PAR NAME']).sum()
out = gb.join(gb_parname, on='PAR NAME', rsuffix='Total')
out.loc[:, 'derived']= out.apply(lambda df: df.value/df.valueTotal, axis=1)
100 loops, best of 3: 6.31 ms per loop
你能解释为什么吗?当我将这个条件添加到顶端,并且将它与您的时间相比时,它似乎几乎相同(11.2毫秒vs 10毫秒)。据我所知,我使用的操作通常是高效的。所有的计算都是goupbys,连接和应用。我认为没有理由期待这个速度非常缓慢 - 我也没有看到它的时间。尽管我愿意被证明是错误的,并且如果我错过了某些东西,我会感兴趣。 –
通常我不喜欢“应用”它有时会杀死性能。而OP只想在DESTCD =='E''行上执行操作。添加新列不是必需的。你的解决方案也很好。时间也取决于机器。我的机器需要1.2秒的解决方案。 – Dark
谢谢!我用了一些修改来允许不同的aggs用于其他cols,比如val2: gb = df。groupby(['DESTCD','PAR NAME'],as_index = False).agg({'value':sum,'value2':lambda x:len(x)}) gb_parname = gb.groupby NAME'])['value']。sum() out = gb.join(gb_parname,on ='PAR NAME',rsuffix ='Total') out.loc [:,'derived'] = out.apply (lambda df:df.value * 100.0/df.valueTotal,axis = 1) out [out [“DESTCD”] =='E'] –
相反的数据透视表,你可以使用基于PAR NAME
多个GROUPBY方法,然后应用操作你要。即
new = df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum()
输出:
PAR NAME abc 16.666667 def 77.777778 Name: value, dtype: float64
如果想定时
%%timeit
df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum()
100 loops, best of 3: 4.03 ms per loop
%%timeit
df = pd.concat([df]*10000)
df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum()
100 loops, best of 3: 15.6 ms per loop
谢谢!这是一个同样好的解决方案,符合我的目的;我选择了正确的答案,只是基于我的电脑上精确的更快的速度 –
我还发现了一种通过旋转来回答这个问题是因为选择的答案同样有效!添加在这里为他人方便:
df.pivot_table(index="PAR NAME",values=["value"],aggfunc={'value':lambda x: x[df.iloc[x.index]['DESTCD']=='E'].sum()*100.0/x.sum()})
逻辑在于aggfunc只与系列作品中的问题,不能引用任何其他系列,直到你通过索引的主要DF得到他们。
您可以添加预期的输出 – Dark