有条件地求和多列中的值

时间:2019-11-20 11:12:26

标签: python pandas

我想根据不同风格的人互相争斗得出的总胜利数。因此,例如,假设战斗机可以有2种战斗方式:XX和JJ。我想计算一个XX风格的战斗机击败另一个XX风格的战斗机的次数,以及该战斗机击败JJ战斗风格的战斗机的次数。

name  style   opp1   style   result1   opp2   style   result2   opp3  style   result3    
 A      XX     C      JJ       win      D      XX      loss       B     JJ      draw
 B      JJ     A      XX       draw     C      JJ      loss       D     XX       win
 C      JJ     A      XX       loss     B      JJ       win       D     XX       win
 D      XX     A      XX        win     B      JJ      loss       C     JJ      loss

这是所需的输出

     XX    JJ
XX          1
JJ   2

我知道我可以通过使用value_counts来获得总的赢,输和平局

df['result1'].value_counts()

但无法弄清楚如何进行此条件求和。

1 个答案:

答案 0 :(得分:1)

您所拥有格式的数据几乎完全无法使用。特别是具有相同名称的列是大熊猫无法处理的,因为您总是会遇到命名冲突。为了使用它,您应该尝试将其转换为“长格式”:

In [39]: df                                                                                                                                                                                                 
Out[39]: 
  name style opp1 style.1 result1 opp2 style.2 result2 opp3 style.3 result3
0    A    XX    C      JJ     win    D      XX    loss    B      JJ    draw
1    B    JJ    A      XX    draw    C      JJ    loss    D      XX     win
2    C    JJ    A      XX    loss    B      JJ     win    D      XX     win
3    D    XX    A      XX     win    B      JJ    loss    C      JJ    loss

In [40]: df2 = pd.concat([df[['name', 'style', 'opp1', 'style.1', 'result1']].rename(columns={'opp1' : 'opponent', 'style.1' : 'style.y', 'result1' : 'result'}), df[['name', 'style', 'opp2', 'style.2', 'r
    ...: esult2']].rename(columns={'opp2' : 'opponent', 'style.2' : 'style.y', 'result2' : 'result'}), df[['name', 'style', 'opp3', 'style.3', 'result3']].rename(columns={'opp3' : 'opponent', 'style.3' : 
    ...: 'style.y', 'result3' : 'result'})])
Out[40]: 
  name style opponent style.y result
0    A    XX        C      JJ    win
1    B    JJ        A      XX   draw
2    C    JJ        A      XX   loss
3    D    XX        A      XX    win
0    A    XX        D      XX   loss
1    B    JJ        C      JJ   loss
2    C    JJ        B      JJ    win
3    D    XX        B      JJ   loss
0    A    XX        B      JJ   draw
1    B    JJ        D      XX    win
2    C    JJ        D      XX    win
3    D    XX        C      JJ   loss

一旦有了其余的内容,基本上就是一个单行纸

In [4]: df3 = df2[df2['result'] == 'win'].groupby(['style', 'style.y'])['result'].count().reset_index()                                                                                                                                                                                                                                                                                                  
Out[4]: 
  style style.y  result
0    JJ      JJ       1
1    JJ      XX       2
2    XX      JJ       1
3    XX      XX       1

In [38]: pd.pivot(df3, index='style', columns='style.y')                                                              
Out[38]: 
        result   
style.y     JJ XX
style            
JJ           1  2
XX           1  1

顺序是字母顺序的,因此它并不完全是您的输出,但是值是相同的。

如果您想使用value_counts(),也可以

In [7]: df3 = df2.groupby(['style', 'style.y'])['result'].value_counts().reset_index(['style', 'style.y']).loc['win', :]

Out[7]: 
       style style.y  result
result                      
win       JJ      JJ       1
win       JJ      XX       2
win       XX      JJ       1
win       XX      XX       1 

,并在pivot之后得到相同的结果。

编辑: 在How can I unpivot or stack a pandas dataframe in the way that I asked?中,我找到了一种更优雅的方法来重塑初始的DataFrame

In [10]: df2 = df.rename(columns={'style.1' : 'oppstyle1', 'style.2' : 'oppstyle2', 'style.3' : 'oppstyle3'})                                                                                                     
Out[10]: 
  name style opp1 oppstyle1 result1 opp2 oppstyle2 result2 opp3 oppstyle3 result3
0    A    XX    C        JJ     win    D        XX    loss    B        JJ    draw
1    B    JJ    A        XX    draw    C        JJ    loss    D        XX     win
2    C    JJ    A        XX    loss    B        JJ     win    D        XX     win
3    D    XX    A        XX     win    B        JJ    loss    C        JJ    loss

In [15]: pd.wide_to_long(df2, ['opp', 'oppstyle', 'result'], i=['name', 'style'], j='i', sep='')                                                                                                            
Out[15]: 
             opp oppstyle result
name style i                    
A    XX    1   C       JJ    win
           2   D       XX   loss
           3   B       JJ   draw
B    JJ    1   A       XX   draw
           2   C       JJ   loss
           3   D       XX    win
C    JJ    1   A       XX   loss
           2   B       JJ    win
           3   D       XX    win
D    XX    1   A       XX    win
           2   B       JJ   loss
           3   C       JJ   loss