【问题标题】:How to dedupe an excel file based on multiple conditions in python?如何根据python中的多个条件对excel文件进​​行重复数据删除?
【发布时间】:2017-12-08 08:28:38
【问题描述】:

我有一个 Excel 文件 (attached here)。我必须针对两个或多个重复的 id 对其进行重复数据删除。 重复数据删除的标准基于多种因素。

  1. 身份证
  2. 类型
  3. 时间

现在,我手动执行重复数据删除的过程是:

  1. 我按升序对 id 进行排序。
  2. 我为每个以 t 开头的 id 设置 Attribute 为 tid。
  3. 我将 xid 用于 id 列中的每个 [id]。如果有重复的 [id](如果两个连续 [id] 的日期相同),我有时会为一个 id 留一个空白。
  4. 对于每个重复的 id,我首先检查类型是茶还是咖啡。如果一个是咖啡,另一个是茶,我们将始终偏爱咖啡并将茶的属性设置为“否”。我们可以获得超过 2 个重复项,因此,我们必须为相同 ID 的所有茶设置“否”。如果我们以相同的 ID 获得两杯咖啡和一份茶,那么我们将根据时间保留最新的一份。
  5. 如果重复的 id 具有相同的类型,那么我们将查看日期并将旧日期的属性设置为“否”。如果日期相同,那么我们将保留一个并将其他属性设置为“否”。 ID 可以超过两个,但过程相同。

我想做的是:

  1. 为以 t 开头的 ID 设置属性为 tid。
  2. 为具有 [] 的 ID 设置属性为 xid。
  3. 如果两个或多个 ID 基于某些条件重复,则在属性中设置 No:

    • 咖啡应该比茶更受欢迎。如果我们有茶和咖啡 重复 id 的类型,我们在每个茶的属性中输入 No 每个重复的 ID。

    • 如果我们为每个重复的 ID 提供一种茶和两种或更多咖啡 然后我们将根据时间(IDs)对剩余的咖啡设置“否” 较旧的时间戳应该是否。)

    • 如果我们对每个重复的 ID 都有相同的类型,那么无论哪个 ID 应保持最新的时间和所有其他属性 应该是没有。

    • 如果我们的所有重复 ID 具有相同的日期和相同的类型,那么我们 只会对除一个之外的所有对象随机设置“否”。

注意:

  • 重复的一、二和三可供我们轻松地根据颜色进行过滤,然后进行重复数据删除。它们基于 Excel 公式:(Duplicate 1=(=IF(B2=B3,1,""), Duplicate2 =(=IF(C1=1,1,""), Duplicate3=(=IF(SUM(C2:D2) >=1,1,""))
  • 我们无法删除行。
  • 我无法找出任何代码,这是我在关键自动化过程中的障碍。
  • 附件属性栏中有No/xid/tid,供参考。

重要问题: - 使用 python 是否可能或可行?

【问题讨论】:

    标签: python excel pandas numpy duplicates


    【解决方案1】:

    我不知道你的问题是否正确,因此我将提供几种不同的方法。

    如果您想删除所有包含相同 id、Type 和 Time 值的行,可以这样做:

    frame=pd.read_excel(io=r"D:\xxxxxx\test.xlsx")
    df=pd.DataFrame(frame)
    drop_dup=df.drop_duplicates(subset=("id","Type","Time"))
    print(drop_dup)
    

    产生:

                  id  Duplicate 1  Duplicate 2  Total Duplicates  \
    0            121349100          NaN          NaN               NaN   
    1            121350610          NaN          NaN               NaN   
    2            124426041          NaN          NaN               NaN   
    3            124436734          NaN          NaN               NaN   
    4            124451775          1.0          NaN               1.0   
    5            124451775          1.0          1.0               1.0   
    7            124463136          NaN          NaN               NaN   
    8            124463568          NaN          NaN               NaN   
    9            124469946          NaN          NaN               NaN   
    10           124474373          NaN          NaN               NaN   
    
    ....
                      Time    Type Attribute  
    0  2017-04-19 18:08:00     Tea       NaN  
    1  2017-04-19 18:08:00     Tea       NaN  
    2  2017-05-05 12:21:00     Tea       NaN  
    3  2017-04-25 15:20:00  Coffee       NaN  
    4  2017-04-05 21:04:00  Coffee        No  
    5  2017-06-05 07:38:00     Tea        No  
    7  2017-06-05 05:40:00  Coffee       NaN  
    8  2017-09-04 23:12:00     Tea       NaN  
    9  2017-04-24 07:48:00     Tea       NaN  
    10 2017-07-05 23:39:00  Coffee       NaN  
    ....
    [77 rows x 7 columns]
    

    这意味着有 7 行具有完全相同的 Type、id 和 Time。 如果您想删除完全相同的行(合并所有列),这将产生所需的结果:

    df=df.drop_duplicates() 
    

    此外:

    dup=df.duplicated(subset=("id","Type","Time"))
    

    返回一个 True/False 数组,指示行是否重复

    0     False
    1     False
    2     False
    3     False
    4     False
    5     False
    6      True
    7     False
    

    如果您想知道 DataFrame 的哪些单个值是重复的,请使用:

    dupl_val=df.apply(pd.Series.duplicated,axis=1)
    
           id  Duplicate 1  Duplicate 2  Total Duplicates   Time   Type  Attribute
    0   False        False        False             False  False  False      False
    1   False        False        False             False  False  False      False
    2   False        False        False             False  False  False      False
    3   False        False        False             False  False  False      False
    4   False        False        False              True  False  False      False
    5   False        False         True              True  False  False      False
    6   False        False        False              True  False  False      False
    

    调用 pd.Series.duplicated 的原因是该方法应用于 DataFrame 的轴 1,这意味着每个单独的 DataFrame 列。 DataFrame 列是 Pandas Series 对象。

    如果您不想删除行,而只是指出哪些值是重复的,请使用:

    dupl_val=df.apply(pd.Series.duplicated,axis=1)
    df=df.where(~dupl_val,"duplicate")
    print(df)
    
    
                        id Duplicate 1 Duplicate 2 Total Duplicates  \
    0            121349100         NaN         NaN              NaN   
    1            121350610         NaN         NaN              NaN   
    2            124426041         NaN         NaN              NaN   
    3            124436734         NaN         NaN              NaN   
    4            124451775           1         NaN        duplicate   
    5            124451775           1   duplicate        duplicate   
    6            124451775         NaN           1        duplicate     
    
                      Time    Type Attribute  
    0  2017-04-19 18:08:00     Tea       NaN  
    1  2017-04-19 18:08:00     Tea       NaN  
    2  2017-05-05 12:21:00     Tea       NaN  
    3  2017-04-25 15:20:00  Coffee       NaN  
    4  2017-04-05 21:04:00  Coffee        No  
    5  2017-06-05 07:38:00     Tea        No  
    6  2017-04-05 21:04:00  Coffee       NaN  
    

    编辑: 如果您只想将 Attribute 列设置为特殊值(我选择了“duplicate”),如果一行中的“id”、“Type”、“Time”值与另一行重复并且不想更改其余列的值,此代码应提供所需的结果:

    frame=pd.read_excel(io=r"D:\xxxxx\test.xlsx")
    df=pd.DataFrame(frame)
    
    
    dup=df.duplicated(subset=("id","Type","Time"))
    
    duplicate="duplicate"
    
    for i in range(len(dup)):
        if dup[i]==True:
            df.loc[i,"Attribute"]=duplicate
    
    print(df)
    
                        id  Duplicate 1  Duplicate 2  Total Duplicates  \
    0            121349100          NaN          NaN               NaN   
    1            121350610          NaN          NaN               NaN   
    2            124426041          NaN          NaN               NaN   
    3            124436734          NaN          NaN               NaN   
    4            124451775          1.0          NaN               1.0   
    5            124451775          1.0          1.0               1.0   
    6            124451775          NaN          1.0               1.0   
    7            124463136          NaN          NaN               NaN   
                      Time    Type  Attribute  
    0  2017-04-19 18:08:00     Tea        NaN  
    1  2017-04-19 18:08:00     Tea        NaN  
    2  2017-05-05 12:21:00     Tea        NaN  
    3  2017-04-25 15:20:00  Coffee        NaN  
    4  2017-04-05 21:04:00  Coffee         No  
    5  2017-06-05 07:38:00     Tea         No  
    6  2017-04-05 21:04:00  Coffee  duplicate 
    7  2017-06-05 05:40:00  Coffee        NaN  
    
    [85 rows x 7 columns]
    

    您可以看到,第 6 行(= 原始 excel 文件中的第 8 行)包含第一个副本。在这种情况下,这是 excel 文件中第 6 行的副本。

    编辑 2

    在我的第二次编辑中,代码现在会将所有重复项(也是第一个)标记为“重复项”。此外,代码不再搜索所有三列(id、时间、类型),而是搜索(id 和时间)或(id 和类型)或(时间和类型)。因此这三个数的所有组合

    dup=[df.duplicated(subset=(i),keep=False) for i in [("id","Type"),("id","Time"),("Time","Type")]]
    duplicate="duplicate"
    
    for i in range(len(dup)):
        for j in range(len(dup[i])):
            if dup[i][j]==True:
                df.loc[j,"Attribute"]=duplicate
    
    
    print(df)
    

    |

           id  Duplicate 1  Duplicate 2  Total Duplicates  \
    0            121349100          NaN          NaN               NaN   
    1            121350610          NaN          NaN               NaN   
    2            124426041          NaN          NaN               NaN   
    3            124436734          NaN          NaN               NaN   
    4            124451775          1.0          NaN               1.0   
    5            124451775          1.0          1.0               1.0   
    6            124451775          NaN          1.0               1.0   
                  Time    Type  Attribute  
    0  2017-04-19 18:08:00     Tea  duplicate  
    1  2017-04-19 18:08:00     Tea  duplicate  
    2  2017-05-05 12:21:00     Tea        NaN  
    3  2017-04-25 15:20:00  Coffee        NaN  
    4  2017-04-05 21:04:00  Coffee  duplicate  
    5  2017-06-05 07:38:00     Tea         No  
    6  2017-04-05 21:04:00  Coffee  duplicate  
    

    有关此函数的更多信息,请阅读:drop_duplicatesduplicated,适用于 Series 和 DataFrame(主要区别在于,对于 Series,函数应用于单个值,而对于 DataFrame,它们分别应用于行以指定列的行)

    【讨论】:

    • 问题是我想在属性列中获取输出,我不想对现有列进行任何更改。
    • 它确实部分工作,直到这一点我也想通了。我遇到的问题是:1)当有两个以上的重复项时,代码仅适用于一个并且仅针对其中一个重复项返回值。我想要的是该值应该针对两个重复项并且应该满足条件。2)它还显示 Duplicate 针对错误的值。我需要它来显示日期较旧的 ID 重复。
    • @PyNoob 1. 如果行中的值 (id,Time,Type) 之前曾出现过一次,则代码在 Attribure 列中重复“重复”。这也意味着第一行没有被标记为重复,而是第二、第三等等。您是否还希望第一行(值的第一次出现被标记为重复)? 2. 目前,如果 thr id 中的值,则代码仅标记重复。类型和时间列是相同的。我说得对吗,如果 id、Time 或 Type(意味着其中之一)重复,您还想将其标记为重复吗?
    • 在我的第二次编辑中,代码现在会将所有重复项(也是第一个)标记为重复项。此外,代码不再搜索所有三列(id、时间、类型),而是搜索“id”或(id 和时间)或(id 和类型)。
    • 不,我非常感谢您所做的事情,但您可能会再次查看我编辑的问题以便更好地理解。 @2Obe
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 2017-01-07
    • 2018-06-12
    • 1970-01-01
    • 2022-08-15
    • 2014-11-09
    相关资源
    最近更新 更多