跨多列使用 isin
using isin across multiple columns
我正在尝试将 .isin 与 ~ 一起使用,这样我就可以根据 2 个数据集中的多列返回唯一行列表。
所以,我有 2 个数据集,共 9 行:
df1 是底部,df2 是顶部(抱歉,我无法让它在下面同时显示,它显示了 1 然后是一行数字)
Index Serial Count Churn
1 9 5 0
2 8 6 0
3 10 2 1
4 7 4 2
5 7 9 2
6 10 2 2
7 2 9 1
8 9 8 3
9 4 3 5
Index Serial Count Churn
1 10 2 1
2 10 2 1
3 9 3 0
4 8 6 0
5 9 8 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
我想根据多于 1 列从 df1 获取不在 df2 中的行列表。
例如,如果我的搜索基于序列号和计数列,我将不会从 df1 返回索引 1 和 2,因为它出现在 df2 中的索引位置 6,与 df1 中的索引位置 4 相同出现在 df2 中的索引位置 2。这同样适用于 df1 中的索引位置 5,因为它位于 df2 中的索引位置 8。
流失列并不重要。
我可以让它工作,但仅基于 1 列,但不超过 1 列。
df2[~df2.Serial.isin(df1.Serial.values)] 有点像我想要的那样,但只在 1 列上。我希望它基于 2 个或更多。
Index Serial Count Churn
3 9 3 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
一种解决方案是与指标合并:
df1 = pd.DataFrame([[10, 2, 0], [9, 4, 1], [9, 8, 1], [8, 6, 1], [9, 8, 1], [1, 9, 1], [10, 3, 1], [6, 7, 1], [4, 8, 1]], columns=['Serial', 'Count', 'Churn'])
df2 = pd.DataFrame([[9, 5, 1], [8, 6, 1], [10, 2, 1], [7, 4, 1], [7, 9, 1], [10, 2, 1], [2, 9, 1], [9, 8, 1], [4, 3, 1]], columns=['Serial', 'Count', 'Churn'])
# merge with indicator on
df_temp = df1.merge(df2[['Serial', 'Count']].drop_duplicates(), on=['Serial', 'Count'], how='left', indicator=True)
res = df_temp.loc[df_temp['_merge'] == 'left_only'].drop('_merge', axis=1)
Output
Serial Count Churn
1 9 4 1
5 1 9 1
6 10 3 1
7 6 7 1
8 4 8 1
我有类似的问题需要解决,我找到了最简单的处理方法,即创建一个临时列,该列由合并的标识符列组成,并在这个新创建的临时列上使用 isin
值。
实现此目的的简单函数如下
from functools import reduce
get_temp_col = lambda df, cols: reduce(lambda x, y: x + df[y].astype('str'), cols, "")
def subset_on_x_columns(df1, df2, cols):
"""
Subsets the input dataframe `df1` based on the missing unique values of input columns
`cols` of dataframe `df2`.
:param df1: Pandas dataframe to be subsetted
:param df2: Pandas dataframe which missing values are going to be
used to subset `df1` by
:param cols: List of column names
"""
df1_temp_col = get_temp_col(df1, cols)
df2_temp_col = get_temp_col(df2, cols)
return df1[~df1_temp_col.isin(df2_temp_col.unique())]
因此对于你的情况,所需要的就是执行:
result_df = subset_on_x_columns(df1, df2, ['Serial', 'Count'])
其中有想要的行:
Index Serial Count Churn
3 9 3 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
这个解决方案的好处是它在使用的列数方面自然是可扩展的,即所有需要的是在输入参数列表 cols
中指定将哪些列用作标识符。
我正在尝试将 .isin 与 ~ 一起使用,这样我就可以根据 2 个数据集中的多列返回唯一行列表。
所以,我有 2 个数据集,共 9 行: df1 是底部,df2 是顶部(抱歉,我无法让它在下面同时显示,它显示了 1 然后是一行数字)
Index Serial Count Churn
1 9 5 0
2 8 6 0
3 10 2 1
4 7 4 2
5 7 9 2
6 10 2 2
7 2 9 1
8 9 8 3
9 4 3 5
Index Serial Count Churn
1 10 2 1
2 10 2 1
3 9 3 0
4 8 6 0
5 9 8 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
我想根据多于 1 列从 df1 获取不在 df2 中的行列表。
例如,如果我的搜索基于序列号和计数列,我将不会从 df1 返回索引 1 和 2,因为它出现在 df2 中的索引位置 6,与 df1 中的索引位置 4 相同出现在 df2 中的索引位置 2。这同样适用于 df1 中的索引位置 5,因为它位于 df2 中的索引位置 8。
流失列并不重要。
我可以让它工作,但仅基于 1 列,但不超过 1 列。
df2[~df2.Serial.isin(df1.Serial.values)] 有点像我想要的那样,但只在 1 列上。我希望它基于 2 个或更多。
Index Serial Count Churn
3 9 3 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
一种解决方案是与指标合并:
df1 = pd.DataFrame([[10, 2, 0], [9, 4, 1], [9, 8, 1], [8, 6, 1], [9, 8, 1], [1, 9, 1], [10, 3, 1], [6, 7, 1], [4, 8, 1]], columns=['Serial', 'Count', 'Churn'])
df2 = pd.DataFrame([[9, 5, 1], [8, 6, 1], [10, 2, 1], [7, 4, 1], [7, 9, 1], [10, 2, 1], [2, 9, 1], [9, 8, 1], [4, 3, 1]], columns=['Serial', 'Count', 'Churn'])
# merge with indicator on
df_temp = df1.merge(df2[['Serial', 'Count']].drop_duplicates(), on=['Serial', 'Count'], how='left', indicator=True)
res = df_temp.loc[df_temp['_merge'] == 'left_only'].drop('_merge', axis=1)
Output
Serial Count Churn
1 9 4 1
5 1 9 1
6 10 3 1
7 6 7 1
8 4 8 1
我有类似的问题需要解决,我找到了最简单的处理方法,即创建一个临时列,该列由合并的标识符列组成,并在这个新创建的临时列上使用 isin
值。
实现此目的的简单函数如下
from functools import reduce
get_temp_col = lambda df, cols: reduce(lambda x, y: x + df[y].astype('str'), cols, "")
def subset_on_x_columns(df1, df2, cols):
"""
Subsets the input dataframe `df1` based on the missing unique values of input columns
`cols` of dataframe `df2`.
:param df1: Pandas dataframe to be subsetted
:param df2: Pandas dataframe which missing values are going to be
used to subset `df1` by
:param cols: List of column names
"""
df1_temp_col = get_temp_col(df1, cols)
df2_temp_col = get_temp_col(df2, cols)
return df1[~df1_temp_col.isin(df2_temp_col.unique())]
因此对于你的情况,所需要的就是执行:
result_df = subset_on_x_columns(df1, df2, ['Serial', 'Count'])
其中有想要的行:
Index Serial Count Churn
3 9 3 0
6 1 9 1
7 10 3 1
8 6 7 1
9 4 8 0
这个解决方案的好处是它在使用的列数方面自然是可扩展的,即所有需要的是在输入参数列表 cols
中指定将哪些列用作标识符。