我正在尝试根据数据框中的两列删除重复的“框”行:
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)
到目前为止我已经尝试过:
df1= df.drop_duplicates(subset=["Week", "Box"], keep=False)
如果同时满足这两个条件,那么我想以“状态!=准备就绪”条件为优先。
预期结果是:
答案 0 :(得分:0)
DataFrame.drop_duplicates(...)
默认保留根据指定的列子集找到的第一项。
换句话说,df.drop_duplicates('Box')
将保留Box
的每个唯一值中的第一个,其余的将丢弃。
因此,我们只需要对数据框进行排序,以便我们要保留的项目是我们遇到的第一个项目。
uniques = df.sort_values('Week').sort_values('Status').drop_duplicates('Box')
这有很多假设:
Status
值可能会破坏此值。 Prep
恰好在Ready
之前按字母顺序排列。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')
我将状态列设置为分类列,然后通过将状态列连接到状态的唯一值来确保“准备就绪”是最大值。这样可以确保排序始终是最后一个。