【问题标题】:Removing duplicated rows but keep the ones with a particular value in one column (pandas python)删除重复的行,但将具有特定值的行保留在一列中(pandas python)
【发布时间】:2016-10-13 03:48:04
【问题描述】:

我想做以下事情:

如果两行在 3 列(“ID”、“symbol”和“date”)中具有完全相同的值,并且在一列(“message”)中具有“X”或“T”,则将两者都删除这些行。但是,如果两行在相同的 3 列中具有相同的值,但在另一列中的值不同于“X”或“T”,则保持不变。

这是我的数据框的示例:

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0" ,"BB-2", "BB-2"], "symbol":["A","A","C","B","B"], "date":["06/24/2014","06/24/2014","06/20/2013","06/25/2014","06/25/2015"], "message": ["T","X","T","",""] })

请注意,前两行的“ID”、“符号”和“日期”列以及“消息”列中的“T”和“X”具有相同的值。我想删除这两行。

但是,最后两行在“ID”、“符号”和“日期”列中具有相同的值,但在“消息”列中为空白(不同于“X”或“T”)。

我有兴趣将该函数应用于具有数百万行的大型数据集。到目前为止,我尝试过的东西消耗了我所有的记忆,

谢谢你,我很感激任何帮助,

【问题讨论】:

  • 只是为了澄清-如果有超过 2 行,您是否要保留重复行?
  • 我应该在我的问题中更清楚地说明这一点。我的数据成对出现。对于每个“X”行,有(或至少应该有)一个“T”行,除“消息”列外,其他列相等。在这种情况下,至少如果数据收集正确,应该只有成对的匹配观察值。

标签: python pandas dataframe duplicates


【解决方案1】:

我认为您可以将 groupbyfilter 一起使用 - 条件是 - 不是 2 具有重复值的行和组中的列 message isin 没有值 TX

import pandas as pd

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0" ,"BB-2", "BB-2"],
                   "symbol":["A","A","C","B","B"],
                   "date":["06/24/2014","06/24/2014","06/20/2013","06/25/2015","06/25/2015"],
                   "message": ["T","X","T","",""] })
print (df) 
     ID        date message symbol
0  AA-1  06/24/2014       T      A
1  AA-1  06/24/2014       X      A
2   C-0  06/20/2013       T      C
3  BB-2  06/25/2015              B
4  BB-2  06/25/2015              B

df1 = df.groupby(['ID','date','symbol']).filter(lambda x: ~((len(x) == 2) & 
                                                          (x.message.isin(['T','X']).all())))
print (df1)
     ID        date message symbol
2   C-0  06/20/2013       T      C
3  BB-2  06/25/2015              B
4  BB-2  06/25/2015              B

Filtration in docs.

comment编辑:

import pandas as pd

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0", "C-0","BB-2", "BB-2"],
                   "symbol":["A","A","C","C", "B","B"],
                   "date":["06/24/2014","06/24/2014","06/20/2013","06/20/2013","06/25/2015","06/25/2015"], 
                   "message": ["T","X","X","X","",""] })
print (df) 
     ID        date message symbol
0  AA-1  06/24/2014       T      A
1  AA-1  06/24/2014       X      A
2   C-0  06/20/2013       X      C
3   C-0  06/20/2013       X      C
4  BB-2  06/25/2015              B
5  BB-2  06/25/2015              B

如果需要删除每个组中带有XT 的值 - 这意味着它也删除了双X 或双T,并且每组的每个len 始终为2

df1 = df.groupby(['ID','date','symbol']).filter(lambda x: ~x.message.isin(['T','X']).all())
print (df1)
     ID        date message symbol
4  BB-2  06/25/2015              B
5  BB-2  06/25/2015              B

如果只需要删除值是TX 的组,您可以先通过message 删除sort_values,然后通过检查第一个值是否为T 和第二个X 来检查每个组中的X团体。 ('T' 是第一个,X 是第二个,因为排序):

df2 = df.sort_values('message')
        .groupby(['ID','date','symbol'], sort=False)
        .filter(lambda x: ((x.message.iloc[0] != 'T') | (x.message.iloc[1] != 'X')))
print (df2)
     ID        date message symbol
4  BB-2  06/25/2015              B
5  BB-2  06/25/2015              B
2   C-0  06/20/2013       X      C
3   C-0  06/20/2013       X      C

【讨论】:

    【解决方案2】:

    这可能对你有用:

    vals = ['X', 'T']
    pd.concat([df[~df.message.isin(vals)], df[df.message.isin(vals)].loc[~df.duplicated(subset=['ID', 'date', 'symbol'], keep=False), :]])
    
         ID        date message symbol
    3  BB-2  06/25/2014              B
    4  BB-2  06/25/2015              B
    2   C-0  06/20/2013       T      C
    

    相当快:

    %%timeit
    pd.concat([df[~df.message.isin(['X', 'T'])], df[df.message.isin(['X', 'T'])].loc[~df.duplicated(subset=['ID', 'date', 'symbol'], keep=False), :]])
    100 loops, best of 3: 1.99 ms per loop
    
    %%timeit
    df.groupby(['ID','date','symbol']).filter(lambda x: ~x.message.isin(['T','X']).all())
    100 loops, best of 3: 2.71 ms per loop
    

    替代方案是给出索引错误。

    【讨论】:

    • If two rows have exactly the same value in... 存在问题 - 您的解决方案过滤所有重复行,而不仅仅是长度为 2。
    • 没错,我只是按照标题说明进行操作。让我们看看需要什么。如果 OP 想要保留超过 2 行的重复行,我的回答将无济于事。
    • concat 函数在这种情况下的运行速度明显快于 groupby
    猜你喜欢
    • 2020-03-24
    • 2012-09-11
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2018-12-29
    • 2019-04-06
    相关资源
    最近更新 更多