Pandas Dataframe:根据条件查找重复行
Pandas Dataframe: Find duplicate rows based on a criteria
我有一个包含以下列和行的数据框:
State Rain Sun Snow Day
1 NJ yes no no 5/31/21
2 NJ yes no no 6/1/21
3 NJ yes no no 6/2/21
4 NJ yes no no 6/3/21
5 NY no no yes 5/31/21
6 NY no yes NULL 6/1/21
7 NY no yes NULL 6/2/21
8 NY no yes NULL 6/3/21
9 IL no yes no 5/31/21
10 IL no yes no 6/1/21
11 IL no yes no 6/2/21
12 IL yes no no 6/3/21
13 FL no yes no 5/31/21
14 FL yes no NULL 6/1/21
15 FL yes NULL NULL 6/2/21
16 FL NULL NULL NULL 6/3/21
此处Rain、Sun、Snow列可以为NULL值,但其他列不能为NULL。此外,如果 Rain 列为空,则 Sun 和 Snow 列也将为 NULL,例如:
NJ NULL NULL NULL 5/31/21 -> Valid
NJ no yes NULL 5/31/21 -> Valid
NJ yes NULL NULL 5/31/21 -> Valid
NJ NULL yes no 5/31/21 -> Invalid
NJ yes NULL no 5/31/21 -> Invalid
NJ NULL NULL no 5/31/21 -> Invalid
我想在此数据集中查找重复项,但要符合特定条件和 return 重复值的索引。
以下情况应视为重复:
案例 1:
NJ yes no no 5/31/21
NJ yes no no 5/31/21
案例二:
NY no yes NULL 6/1/21
NY no yes NULL 6/1/21
案例 3:
FL no no no 6/1/21
FL no no NULL 6/1/21
FL no NULL NULL 6/1/21
FL NULL NULL NULL 6/1/21
我能够解决前两种情况:
def find_duplicates(df: pd.DataFrame):
dup_rows = df.duplicated(subset=['State', 'Rain', 'Sun', 'Snow', 'Day'], keep=False)
dup_df = df[dup_rows]
dup_df = dup_df.reset_index()
dup_df.rename(columns={'index': 'row'}, inplace=True)
group = dup_df.groupby(['State', 'Rain', 'Sun', 'Snow', 'Day'], dropna=False)
dup_lst = [grp['row'].to_list() for ind, grp in group]
return dup_lst
我不确定如何处理第 3 种情况,我是 pandas 数据框的新手,如有任何帮助,我们将不胜感激。
也许这就是您要找的东西?
import numpy as np
import pandas as pd
def colwise_dups(df, cols):
return df[
np.array(
[
(row.drop(index=cols).values == df.drop(columns=cols).values).all(
axis=1
)
for _, row in df[
(df[cols] == ["NULL"] * len(cols)).all(axis=1)
].iterrows()
]
).any(axis=0)
]
cols = []
duplicates = pd.DataFrame()
for col in ["Rain", "Sun", "Snow"][::-1]:
cols.append(col)
duplicates = pd.concat([duplicates, colwise_dups(df, cols)]).drop_duplicates()```
如果我对问题的理解正确,我认为您可以通过创建两个分别用 'NULL' 替换为 'yes' 和 'no' 的临时数据框来实现您的目标。然后您可以根据重复项进行过滤。
最小示例:
df = pd.DataFrame({'State': 'NJ NJ NY NY FL FL FL FL'.split(' '),
'Rain': 'yes yes no no no no no NULL'.split(' '),
'Sun': 'no no yes yes no no NULL NULL'.split(' '),
'Snow': 'no no NULL NULL no NULL NULL NULL'.split(' '),
'Day': '5/31/21 5/31/21 6/1/21 6/1/21 6/1/21 6/1/21 6/1/21 6/1/21' .split(' ')})
tmp = df.replace('NULL', 'no')
tmp2 = df.replace('NULL', 'yes')
df[~tmp.duplicated() & ~tmp2.duplicated()]
给出以下输出:
State Rain Sun Snow Day
0 NJ yes no no 5/31/21
2 NY no yes NULL 6/1/21
4 FL no no no 6/1/21
我有一个包含以下列和行的数据框:
State Rain Sun Snow Day
1 NJ yes no no 5/31/21
2 NJ yes no no 6/1/21
3 NJ yes no no 6/2/21
4 NJ yes no no 6/3/21
5 NY no no yes 5/31/21
6 NY no yes NULL 6/1/21
7 NY no yes NULL 6/2/21
8 NY no yes NULL 6/3/21
9 IL no yes no 5/31/21
10 IL no yes no 6/1/21
11 IL no yes no 6/2/21
12 IL yes no no 6/3/21
13 FL no yes no 5/31/21
14 FL yes no NULL 6/1/21
15 FL yes NULL NULL 6/2/21
16 FL NULL NULL NULL 6/3/21
此处Rain、Sun、Snow列可以为NULL值,但其他列不能为NULL。此外,如果 Rain 列为空,则 Sun 和 Snow 列也将为 NULL,例如:
NJ NULL NULL NULL 5/31/21 -> Valid
NJ no yes NULL 5/31/21 -> Valid
NJ yes NULL NULL 5/31/21 -> Valid
NJ NULL yes no 5/31/21 -> Invalid
NJ yes NULL no 5/31/21 -> Invalid
NJ NULL NULL no 5/31/21 -> Invalid
我想在此数据集中查找重复项,但要符合特定条件和 return 重复值的索引。 以下情况应视为重复:
案例 1:
NJ yes no no 5/31/21
NJ yes no no 5/31/21
案例二:
NY no yes NULL 6/1/21
NY no yes NULL 6/1/21
案例 3:
FL no no no 6/1/21
FL no no NULL 6/1/21
FL no NULL NULL 6/1/21
FL NULL NULL NULL 6/1/21
我能够解决前两种情况:
def find_duplicates(df: pd.DataFrame):
dup_rows = df.duplicated(subset=['State', 'Rain', 'Sun', 'Snow', 'Day'], keep=False)
dup_df = df[dup_rows]
dup_df = dup_df.reset_index()
dup_df.rename(columns={'index': 'row'}, inplace=True)
group = dup_df.groupby(['State', 'Rain', 'Sun', 'Snow', 'Day'], dropna=False)
dup_lst = [grp['row'].to_list() for ind, grp in group]
return dup_lst
我不确定如何处理第 3 种情况,我是 pandas 数据框的新手,如有任何帮助,我们将不胜感激。
也许这就是您要找的东西?
import numpy as np
import pandas as pd
def colwise_dups(df, cols):
return df[
np.array(
[
(row.drop(index=cols).values == df.drop(columns=cols).values).all(
axis=1
)
for _, row in df[
(df[cols] == ["NULL"] * len(cols)).all(axis=1)
].iterrows()
]
).any(axis=0)
]
cols = []
duplicates = pd.DataFrame()
for col in ["Rain", "Sun", "Snow"][::-1]:
cols.append(col)
duplicates = pd.concat([duplicates, colwise_dups(df, cols)]).drop_duplicates()```
如果我对问题的理解正确,我认为您可以通过创建两个分别用 'NULL' 替换为 'yes' 和 'no' 的临时数据框来实现您的目标。然后您可以根据重复项进行过滤。
最小示例:
df = pd.DataFrame({'State': 'NJ NJ NY NY FL FL FL FL'.split(' '),
'Rain': 'yes yes no no no no no NULL'.split(' '),
'Sun': 'no no yes yes no no NULL NULL'.split(' '),
'Snow': 'no no NULL NULL no NULL NULL NULL'.split(' '),
'Day': '5/31/21 5/31/21 6/1/21 6/1/21 6/1/21 6/1/21 6/1/21 6/1/21' .split(' ')})
tmp = df.replace('NULL', 'no')
tmp2 = df.replace('NULL', 'yes')
df[~tmp.duplicated() & ~tmp2.duplicated()]
给出以下输出:
State Rain Sun Snow Day
0 NJ yes no no 5/31/21
2 NY no yes NULL 6/1/21
4 FL no no no 6/1/21