当一个值代表一组值时,我试图找到一种有效的方法来查找重复的行:
df = pd.DataFrame(
{
"ID": ["one", "two", "two", "two", "one"],
"condition1": ["all", "red", "all", "red", "red"],
"condition2": ["yellow", "black", "black", "orange", "black"],
}
)
在本例中,'all'表示当前列中的所有颜色,因此ID 'two'是重复的,因为我们有:(两个,红、黑)[2,all,black] where "all"可以是黑色的。但最关键的一点是不重复,因为在第二个条件下颜色不一样。
我想到的最好的方法是扩展列并调用duplicate(),问题是这种解决方案在正常用例中会产生一个非常大的数据框架。
df.loc[df.condition1=='all','condition1'] = set(df.condition1)-{'all'}
df.loc[df.condition2=='all','condition2'] = set(df.condition2)-{'all'}
df = df.explode('condition1')
df = df.explode('condition2')
df.duplicated()
有没有更标准/有效的方法来解决这个问题?我还在考虑一个接受关键字"all"作为所有可能性的小组,或者可能通过id迭代并单独检查值为"all"的位置。
编辑:也许这个解决方案,每个ID分裂和迭代,可以做得很好,但也许还有更好的方法。
我对你这个有趣的问题的看法如下。
使用您提供的玩具数据框架,修改以考虑更多用例:
import pandas as pd
df = pd.DataFrame(
{
"ID": ["one", "two", "two", "one", "one", "two", "one"],
"condition1": ["all", "red", "all", "blue", "red", "brown", "all"],
"condition2": ["yellow", "black", "black", "yellow", "all", "orange", "all"],
}
)
print(df)
# Output
ID condition1 condition2
0 one all yellow
1 two red black
2 two all black
3 one blue yellow
4 one red all
5 two brown orange
6 one all all
这是另一种方法,在我的机器上,它更慢(执行500次平均0.014秒,而您的方法为0.002秒),但消耗的内存少得多,因为它依赖于生成器表达式,并提供更容易理解的结果:
def find_duplicates(df, col, other_col):
all_condition1 = [
condition for condition in df[col].unique().tolist() if condition != "all"
]
all_condition2 = [
condition for condition in df[other_col].unique().tolist() if condition != "all"
]
duplicates = pd.concat(
(
df.assign(temp1=df[col].mask(df[col] == "all", condition1))
.assign(temp2=df[other_col].mask(df[other_col] == "all", condition2))
.pipe(
lambda df_: df_[
df_.duplicated(subset=["ID", "temp1", "temp2"], keep=False)
].drop(columns=["temp1", "temp2"])
)
for condition1 in all_condition1
for condition2 in all_condition2
)
)
return duplicates[~duplicates.index.duplicated(keep="first")].sort_index()
duplicates = find_duplicates(df, "condition1", "condition2")
print(duplicates)
# Output
ID condition1 condition2
0 one all yellow
1 two red black
2 two all black
3 one blue yellow
4 one red all
6 one all all