Python Pandas运行与重置的总计

时间:2017-11-09 09:43:46

标签: python pandas sum cumsum

我想执行以下任务。给定2列(好的和坏的)我想用运行总计替换两列的任何行。以下是当前数据帧以及所需数据帧的示例。

编辑:我应该添加我的意图。我试图使用连续变量作为输入创建相同的binned(在本例中为20)变量。我知道pandas cut和qcut函数是可用的,但返回的结果将为好/坏率(需要计算证据和信息值的权重)。分子或分母中的零将不允许数学计算起作用。

   d={'AAA':range(0,20),
      'good':[3,3,13,20,28,32,59,72,64,52,38,24,17,19,12,5,7,6,2,0],
      'bad':[0,0,1,1,1,0,6,8,10,6,6,10,5,8,2,2,1,3,1,1]}
   df=pd.DataFrame(data=d)
   print(df)

以下解释了我需要对上述数据帧做些什么。 enter image description here

粗略地说,无论何时我遇到任何一列的零,我都需要使用一个运行总计,该列对于包含零的列具有非零值的下一行不为零。

这是所需的输出:

dd={'AAA':range(0,16),
    'good':[19,20,60,59,72,64,52,38,24,17,19,12,5,7,6,2],
    'bad':[1,1,1,6,8,10,6,6,10,5,8,2,2,1,3,2]}

desired_df=pd.DataFrame(data=dd)    
print(desired_df) 

2 个答案:

答案 0 :(得分:0)

我的解决方案的基本思想是从非零值的cumsum创建一列,以便将具有下一个非零值的零值合并到一个组中。然后你可以使用groupby + sum来获得你想要的值。

two_good = df.groupby((df['bad']!=0).cumsum().shift(1).fillna(0))['good'].sum()
two_bad = df.groupby((df['good']!=0).cumsum().shift(1).fillna(0))['bad'].sum()

two_good = two_good.loc[two_good!=0].reset_index(drop=True)
two_bad = two_bad.loc[two_bad!=0].reset_index(drop=True)

new_df = pd.concat([two_bad, two_good], axis=1).dropna()
print(new_df)
    bad  good
0     1  19.0
1     1  20.0
2     1  28.0
3     6  91.0
4     8  72.0
5    10  64.0
6     6  52.0
7     6  38.0
8    10  24.0
9     5  17.0
10    8  19.0
11    2  12.0
12    2   5.0
13    1   7.0
14    3   6.0
15    1   2.0

此代码将您的蚀刻情况视为与您想要的输出不同的尾随零,简单地将其剪掉。你必须添加一些额外的代码来捕获具有不同逻辑的代码。

答案 1 :(得分:0)

P.Tillmann。感谢您对此的帮助。对于更高级的读者,我会假设你像我一样发现这个代码令人震惊。我非常乐意接受任何使其更加精简的建议。

d={'AAA':range(0,20),
  'good':[3,3,13,20,28,32,59,72,64,52,38,24,17,19,12,5,7,6,2,0],
  'bad':[0,0,1,1,1,0,6,8,10,6,6,10,5,8,2,2,1,3,1,1]}
df=pd.DataFrame(data=d)
print(df)

row_good=0
row_bad=0
row_bad_zero_count=0
row_good_zero_count=0
row_out='NO'
crappy_fix=pd.DataFrame()
for index,row in df.iterrows():
    if row['good']==0 or row['bad']==0:
        row_bad += row['bad']
        row_good += row['good']
        row_bad_zero_count += 1
        row_good_zero_count += 1
        output_ind='1'
        row_out='NO'
    elif index+1 < len(df) and (df.loc[index+1,'good']==0 or    df.loc[index+1,'bad']==0):
        row_bad=row['bad']
        row_good=row['good'] 
        output_ind='2'
        row_out='NO'    
    elif (row_bad_zero_count > 1 or row_good_zero_count > 1) and row['good']!=0 and row['bad']!=0:
        row_bad += row['bad']
        row_good += row['good']
        row_bad_zero_count=0
        row_good_zero_count=0    
        row_out='YES'
        output_ind='3'
    else:
        row_bad=row['bad']
        row_good=row['good']
        row_bad_zero_count=0
        row_good_zero_count=0
        row_out='YES'
        output_ind='4'

    if ((row['good']==0 or row['bad']==0) 
        and (index > 0 and (df.loc[index-1,'good']!=0 or df.loc[index-1,'bad']!=0))
        and row_good != 0 and row_bad != 0):
        row_out='YES'

    if row_out=='YES':
        temp_dict={'AAA':row['AAA'],
                   'good':row_good,
                   'bad':row_bad}
        crappy_fix=crappy_fix.append([temp_dict],ignore_index=True)
        print(str(row['AAA']),'-',
              str(row['good']),'-',
              str(row['bad']),'-',
              str(row_good),'-',
              str(row_bad),'-',
              str(row_good_zero_count),'-',
              str(row_bad_zero_count),'-',
              row_out,'-',
              output_ind) 

print(crappy_fix)