这是df的一部分:
NUMBER MONEY
12345 20
12345 -20
12345 20
12345 20
123456 10
678910 7.6
123457 3
678910 -7.6
我要删除数字相同但钱相反的行。
理想的结果如下:
NUMBER MONEY
12345 20
12345 20
123456 10
123457 3
注意:这些条目不是一一对应的(我的意思是总数是一个奇数)。
例如,有四个条目是[Number] 12345。
其中三个[Money]是20,一个[Money]是-20。
我只想删除两个相反的[Money],并保留另外两个货币为20的货币。
答案 0 :(得分:0)
这是一个解决方案。 输入:
df_work
NUMBER MONEY
0 12345 20.0
1 12345 -20.0
2 12345 20.0
3 12345 20.0
4 123456 10.0
5 678910 7.6
6 123457 3.0
7 678910 -7.6
代码
df_grouped = df_work.groupby('NUMBER').sum().rename(columns={'MONEY': 'MONEY_SUMMED'})
df_work['MONEY'] = np.abs(df_work['MONEY'])
df_abs_unique = df_work[['NUMBER','MONEY']].drop_duplicates()
df_money = pd.merge(df_grouped, df_abs_unique, on='NUMBER')
df_money['NUMBER_TO_OCCUR'] = df_money['MONEY_SUMMED']/df_money['MONEY']
df_result = pd.DataFrame()
for number in df_money['NUMBER_TO_OCCUR'].unique():
if number == 0:
continue
df_number = df_money[df_money['NUMBER_TO_OCCUR'] == number]
df_result = pd.concat(int(number)*[df_number] + [df_result])
输出
df_result.drop(['NUMBER_TO_OCCUR', 'MONEY_SUMMED'], 1)
NUMBER MONEY
1 123456 10.0
2 123457 3.0
0 12345 20.0
0 12345 20.0
我们用建立每个数字的总和除以绝对货币来获得有关每个数字必须多久出现一次的信息。最后的循环效率不高,但仍然有效。
答案 1 :(得分:0)
这是使用groupby
和apply
以及自定义函数来匹配和删除对的解决方案。
def remove_pairs(x):
positive = x.loc[x['MONEY'] > 0].index.values
negative = x.loc[x['MONEY'] < 0].index.values
for i, j in zip(positive, negative):
x = x.drop([i, j])
return x
df['absvalues'] = df['MONEY'].abs()
dd = df.groupby(['NUMBER', 'absvalues']).apply(remove_pairs)
dd.reset_index(drop=True, inplace=True)
dd.drop('absvalues', axis=1, inplace=True)
'absvalue'
列的绝对值为'MONEY'
,以对groupby
执行双索引选择,然后自定义函数将成对的行拖放成对,以选择正数和负数。 / p>
最后两行只是进行一些清洁。使用示例数据框,最终结果dd
为:
NUMBER MONEY
0 12345 20.0
1 12345 20.0
2 123456 10.0
3 123457 3.0