如何根据python中的多个条件对excel文件进​​行重复数据删除?

Posted

技术标签:

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

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

    身份证 类型 时间

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

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

我想做的是:

    为以 t 开头的 ID 设置属性为 tid。 为具有 [] 的 ID 设置属性为 xid。

    如果两个或多个 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 是否可能或可行?

【问题讨论】:

【参考方案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_duplicates、duplicated,适用于 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

以上是关于如何根据python中的多个条件对excel文件进​​行重复数据删除?的主要内容,如果未能解决你的问题,请参考以下文章

在Python中按日期对excel文件进​​行排序[关闭]

Excel - UDF 函数,用于根据条件从多个工作表中获取 SUM 值

如何根据python中的多个条件计算列中的唯一行

在excel中怎样根据多个条件进行求和

Python 也可以实现 Excel 中的 “Vlookup” 函数?

Excel 根据条件合并几行