如何根据其他列中的一个条件和两个条件删除重复项

时间:2019-06-03 21:20:17

标签: python pandas dataframe duplicates

我正在尝试根据数据框中的两列删除重复的“框”行:

enter image description here

import pandas as pd
d = {'Box': ['A1', 'A1', 'A2', 'A3', 'A4', 'A5', 'A5'], 'Status': ['Prep', 'Ready', 'Prep', 'Prep', 'Ready', 'Prep', 'Ready'], 'Week':[11, 12, 12, 13, 11, 10, 11], 'QTY': [6, 7, 6, 8, 5, 8, 7]}
df = pd.DataFrame(data=d)
  • 如果有重复的Box号,则以分钟(周)为准。
  • 如果有重复的Box号,则采用状态!= Ready(不等于ready)

到目前为止我已经尝试过:

df1= df.drop_duplicates(subset=["Week", "Box"], keep=False)

如果同时满足这两个条件,那么我想以“状态!=准备就绪”条件为优先。

预期结果是:

enter image description here

2 个答案:

答案 0 :(得分:0)

DataFrame.drop_duplicates(...)默认保留根据指定的列子集找到的第一项。

换句话说,df.drop_duplicates('Box')将保留Box的每个唯一值中的第一个,其余的将丢弃。

因此,我们只需要对数据框进行排序,以便我们要保留的项目是我们遇到的第一个项目。

uniques = df.sort_values('Week').sort_values('Status').drop_duplicates('Box')

这有很多假设:

  1. 您的数据很小,因此像这样进行两次排序不会太昂贵。
  2. 您没有其他Status值可能会破坏此值。 Prep恰好在Ready之前按字母顺序排列。
  3. 您没有任何示例,其中Week中的Ready值较低的Status-因为我们最后按Status进行排序,所以在这种情况下我们将优先级较高。如果您想先按Week进行过滤,可以将它们反转。

编辑:

包含您发布的数据:

>>> import pandas as pd
>>> d = {'Box': ['A1', 'A1', 'A2', 'A3', 'A4', 'A5', 'A5'], 'Status': ['Prep', 'Ready', 'Prep', 'Prep', 'Ready', 'Prep', 'Ready'], 'Week':[11, 12, 12, 13, 11, 10, 11], 'QTY': [6, 7, 6, 8, 5, 8, 7]}
>>> df = pd.DataFrame(data=d)
>>> df.sort_values('Status').sort_values('Week').drop_duplicates('Box').sort_index()
  Box  QTY Status  Week
0  A1    6   Prep    11
2  A2    6   Prep    12
3  A3    8   Prep    13
4  A4    5  Ready    11
5  A5    8   Prep    10

对于上述假设2,我建议对您的状态进行排序,然后在此基础上添加一列。

order = { 'Prep' : 1, 'Ready' : 2 }
df['status_order'] = df['Status'].apply(lambda x: order[x])

然后,您可以按此列而不是Status进行排序。这一般适用于处理非Ready状态的重复项。

答案 1 :(得分:0)

x = df['Status'].unique()

df['Status'] = pd.Categorical(df['Status'], categories= np.concatenate([x[x!='Ready'], ['Ready']]), ordered= True)

df.sort_values(['Status', 'Week']).drop_duplicates(subset=["Box"]).sort_values('Box')

我将状态列设置为分类列,然后通过将状态列连接到状态的唯一值来确保“准备就绪”是最大值。这样可以确保排序始终是最后一个。