Python/Pandas - 删除非重复行

4

我有这样的DataFrame:

        product_id          dt  stock_qty
226870     2948259  2017-11-11     17.000
233645     2948259  2017-11-12     17.000
240572     2948260  2017-11-13      5.000
247452     2948260  2017-11-14      5.000
233644     2948260  2017-11-12      5.000
226869     2948260  2017-11-11      5.000
247451     2948262  2017-11-14     -2.000
226868     2948262  2017-11-11     -1.000  <- not duplicated
240571     2948262  2017-11-13     -2.000
240570     2948264  2017-11-13      5.488
233643     2948264  2017-11-12      5.488
244543     2948269  2017-11-11      2.500
247450     2948276  2017-11-14      3.250
226867     2948276  2017-11-11      3.250

我需要删除其中 stock_qty 不同但是product_id 值相同的行。因此,我应该得到如下的 DataFrame:
        product_id          dt  stock_qty
226870     2948259  2017-11-11     17.000
233645     2948259  2017-11-12     17.000
240572     2948260  2017-11-13      5.000
247452     2948260  2017-11-14      5.000
233644     2948260  2017-11-12      5.000
226869     2948260  2017-11-11      5.000
240570     2948264  2017-11-13      5.488
233643     2948264  2017-11-12      5.488
244543     2948269  2017-11-11      2.500
247450     2948276  2017-11-14      3.250
226867     2948276  2017-11-11      3.250

感谢您的帮助!
4个回答

4

您需要使用drop_duplicates来获取所有product_id值,然后通过与另一个条件链接的isin进行排除,使用异或(^)运算符:

m1 = df['product_id'].isin(df.drop_duplicates('stock_qty', keep=False)['product_id'])
m2 = df.duplicated('product_id', keep=False)

df = df[m1 ^ m2]
print (df)
        product_id          dt  stock_qty
226870     2948259  2017-11-11     17.000
233645     2948259  2017-11-12     17.000
240572     2948260  2017-11-13      5.000
247452     2948260  2017-11-14      5.000
233644     2948260  2017-11-12      5.000
226869     2948260  2017-11-11      5.000
240570     2948264  2017-11-13      5.488
233643     2948264  2017-11-12      5.488
244543     2948269  2017-11-11      2.500
247450     2948276  2017-11-14      3.250
226867     2948276  2017-11-11      3.250

详细信息:

print (m1)
226870    False
233645    False
240572    False
247452    False
233644    False
226869    False
247451     True
226868     True
240571     True
240570    False
233643    False
244543     True
247450    False
226867    False
Name: product_id, dtype: bool

print (m2)
226870     True
233645     True
240572     True
247452     True
233644     True
226869     True
247451     True
226868     True
240571     True
240570     True
233643     True
244543    False
247450     True
226867     True
dtype: bool

但是我需要完全排除产品ID为2948262的行,因为它们具有与其他具有相同产品ID的行不重复的行。 - user8407067
如果我有一个与相同product_it的行,这段代码也会将其排除在外,但它不应该这样做。 - user8407067
我不明白。你能否将示例数据更改为所需的输出?或者你认为如果第三个product_id是唯一的,例如123,那么这一行应该被删除吗?谢谢。 - jezrael
我已经编辑了问题。我添加了一行产品ID为2948269,它不需要被删除。 - user8407067
请检查一下 ;) - jezrael

4

@jezrael的解决方案是最优的,但另一种方法是使用groupbyfilter

df.groupby(['product_id','stock_qty']).filter(lambda x: len(x)>1)

输出:

        product_id          dt  stock_qty
226870     2948259  2017-11-11     17.000
233645     2948259  2017-11-12     17.000
240572     2948260  2017-11-13      5.000
247452     2948260  2017-11-14      5.000
233644     2948260  2017-11-12      5.000
226869     2948260  2017-11-11      5.000
247451     2948262  2017-11-14     -2.000
240571     2948262  2017-11-13     -2.000
240570     2948264  2017-11-13      5.488
233643     2948264  2017-11-12      5.488
247450     2948276  2017-11-14      3.250
226867     2948276  2017-11-11      3.250

这将删除重复项,但将保留任何可能的三个或更多重复项... - Monica Heddneck

4
通过使用drop_duplicates函数
df.drop(df.drop_duplicates(['stock_qty', 'product_id'], keep=False).index)
Out[797]: 
        product_id          dt  stock_qty
226870     2948259  2017-11-11     17.000
233645     2948259  2017-11-12     17.000
240572     2948260  2017-11-13      5.000
247452     2948260  2017-11-14      5.000
233644     2948260  2017-11-12      5.000
226869     2948260  2017-11-11      5.000
247451     2948262  2017-11-14     -2.000
240571     2948262  2017-11-13     -2.000
240570     2948264  2017-11-13      5.488
233643     2948264  2017-11-12      5.488
247450     2948276  2017-11-14      3.250
226867     2948276  2017-11-11      3.250

0

使用 loc[] 可以过滤掉重复的行并将其赋值给原始数据框。

df = df.loc[df.duplicated(subset=['product_id','stock_qty'], keep=False)]

另外,keep=False参数将所有重复的行标记为True,如果您只想要第一个或最后一个,请使用keep='first'keep='last'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接