跨多列使用 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 中指定将哪些列用作标识符。