python中两个数据帧逐行的不常见值

python中两个数据帧逐行的不常见值,python,pandas,dataframe,Python,Pandas,Dataframe,我有两个数据帧df1和df2。两者中的第一列都是客户ID,它是int,但其他列包含各种字符串值。我想生成一个新的数据帧df3,它包含每个客户ID的一组值,这些值可以在df2中找到,但不能在df1中找到 例如: df1: v1 v2 v3 v4 cust 1 A B B A 2 A A A A 3 B B A A 4 B C A A v1 v2 v3 v4 cust 1

我有两个数据帧
df1
df2
。两者中的第一列都是客户ID,它是
int
,但其他列包含各种字符串值。我想生成一个新的数据帧
df3
,它包含每个客户ID的一组值,这些值可以在
df2
中找到,但不能在
df1
中找到

例如:

df1

     v1 v2 v3 v4
cust            
1     A  B  B  A
2     A  A  A  A
3     B  B  A  A
4     B  C  A  A
     v1 v2 v3 v4
cust            
1     A  A  C  B
2     A  A  C  B
3     C  B  B  A
4     C  B  B  A
df2

     v1 v2 v3 v4
cust            
1     A  B  B  A
2     A  A  A  A
3     B  B  A  A
4     B  C  A  A
     v1 v2 v3 v4
cust            
1     A  A  C  B
2     A  A  C  B
3     C  B  B  A
4     C  B  B  A
预期产出:

cust
1       {C}
2    {B, C}
3       {C}
4        {}
[2]中的
:df_2=pd.DataFrame({“KundelID”:list(范围(1,11)),
…:'V1':列表('AACCBBBCCC'),
…:“V2”:列表('AABBBCCCAA'),
…:'V3':列表('ccbbbaab'),
…:'V4':列表('bbaacaaab')})
…:df_1=pd.DataFrame({“KundelID”:list(范围(1,11)),
…:“V1”:列表('aabbcccc'),
…:“V2”:列表('babcccaaa'),
…:'V3':列表('baaaabbb'),
…:“V4”:列表('aaccbb')})
In[3]:df_1
出[3]:
KundelID V1 V2 V3 V4
0 1 A B A
1 2 A A
2 3 B A A
3 4 B C A
4 5 C A C
5 6 C A C
6 7 C B C
7 8 C A B C
8 9 C A B B
9 10 C A B B
In[4]:df_2
出[4]:
KundelID V1 V2 V3 V4
0 1 A C B
1 2 A C B
2 3 C B A
3 4 C B A
4 5 B C
5 6 B C B A
6 7 B C B A
7 8 C A
8 9 C A A
9 10 C A B B
在[7]中:pd.DataFrame({“KundeID”:df_2.KundelID,
…:'Not-in-dfu_1':[','.连接([i-for-i-in-dfu 2_,if-Not-in-dfu 2_]if[i-for-i-in-dfu 2_,if-Not-in-dfu 1_]else-None-for-dfu 1_,dfu 2_-in-zip(df_1.T[1:]apply(np.unique),df_2.T[1:]apply(np.unique))})
出[7]:
KundeID不在df_1内
01摄氏度
1 2 B,C
2 3 C
3.4无
4.5 B
5.6 B
67A
7.8无
8.9无
9 10无
在[2]中:df_2=pd.DataFrame({“KundelID”:list(范围(1,11)),
…:'V1':列表('AACCBBBCCC'),
…:“V2”:列表('AABBBCCCAA'),
…:'V3':列表('ccbbbaab'),
…:'V4':列表('bbaacaaab')})
…:df_1=pd.DataFrame({“KundelID”:list(范围(1,11)),
…:“V1”:列表('aabbcccc'),
…:“V2”:列表('babcccaaa'),
…:'V3':列表('baaaabbb'),
…:“V4”:列表('aaccbb')})
In[3]:df_1
出[3]:
KundelID V1 V2 V3 V4
0 1 A B A
1 2 A A
2 3 B A A
3 4 B C A
4 5 C A C
5 6 C A C
6 7 C B C
7 8 C A B C
8 9 C A B B
9 10 C A B B
In[4]:df_2
出[4]:
KundelID V1 V2 V3 V4
0 1 A C B
1 2 A C B
2 3 C B A
3 4 C B A
4 5 B C
5 6 B C B A
6 7 B C B A
7 8 C A
8 9 C A A
9 10 C A B B
在[7]中:pd.DataFrame({“KundeID”:df_2.KundelID,
…:'Not-in-dfu_1':[','.连接([i-for-i-in-dfu 2_,if-Not-in-dfu 2_]if[i-for-i-in-dfu 2_,if-Not-in-dfu 1_]else-None-for-dfu 1_,dfu 2_-in-zip(df_1.T[1:]apply(np.unique),df_2.T[1:]apply(np.unique))})
出[7]:
KundeID不在df_1内
01摄氏度
1 2 B,C
2 3 C
3.4无
4.5 B
5.6 B
67A
7.8无
8.9无
9 10无

想法是将每行中的所有值转换为一个
集合。然后,我们可以为每个客户ID设置差异。这避免了循环和列表理解:

df3 = (
    pd
    .concat([
        df1.reindex(index=df2.index).apply(set, axis=1),
        df2.apply(set, axis=1),
    ], axis=1)
    .apply(lambda r: r[1].difference(r[0]), axis=1)
)
print(df3)
# Out:
cust
1       {C}
2    {B, C}
3       {C}
4        {}
注释

     v1 v2 v3 v4
cust            
1     A  B  B  A
2     A  A  A  A
3     B  B  A  A
4     B  C  A  A
     v1 v2 v3 v4
cust            
1     A  A  C  B
2     A  A  C  B
3     C  B  B  A
4     C  B  B  A
  • df1.reindex(index=df2.index)
    用于在
    df1
    df2
    中缺少某些ID的情况下使用
  • 将输出转换为其他内容而不是
    ,这很简单。例如,'.join(r[1].difference(r[0])
  • ,因为lambda将生成字符串 设置

         v1 v2 v3 v4
    cust            
    1     A  B  B  A
    2     A  A  A  A
    3     B  B  A  A
    4     B  C  A  A
    
         v1 v2 v3 v4
    cust            
    1     A  A  C  B
    2     A  A  C  B
    3     C  B  B  A
    4     C  B  B  A
    
    为了便于将来参考,为了便于再现示例,最好提供一些代码,这些代码可以由SO直接复制/粘贴,以便快速开始解决您的问题

    df1 = pd.read_csv(io.StringIO("""
    1 A B B A
    2 A A A A
    3 B B A A
    4 B C A A
    """), sep=' ', names='cust v1 v2 v3 v4'.split()).set_index('cust')
    
    df2 = pd.read_csv(io.StringIO("""
    1 A A C B
    2 A A C B
    3 C B B A
    4 C B B A
    """), sep=' ', names='cust v1 v2 v3 v4'.split()).set_index('cust')
    

    其思想是将每行中的所有值转换为一个
    集合
    。然后,我们可以为每个客户ID设置差异。这避免了循环和列表理解:

    df3 = (
        pd
        .concat([
            df1.reindex(index=df2.index).apply(set, axis=1),
            df2.apply(set, axis=1),
        ], axis=1)
        .apply(lambda r: r[1].difference(r[0]), axis=1)
    )
    print(df3)
    # Out:
    cust
    1       {C}
    2    {B, C}
    3       {C}
    4        {}
    
    注释

         v1 v2 v3 v4
    cust            
    1     A  B  B  A
    2     A  A  A  A
    3     B  B  A  A
    4     B  C  A  A
    
         v1 v2 v3 v4
    cust            
    1     A  A  C  B
    2     A  A  C  B
    3     C  B  B  A
    4     C  B  B  A
    
  • df1.reindex(index=df2.index)
    用于在
    df1
    df2
    中缺少某些ID的情况下使用
  • 将输出转换为其他内容而不是
    ,这很简单。例如,'.join(r[1].difference(r[0])
  • ,因为lambda将生成字符串 设置

         v1 v2 v3 v4
    cust            
    1     A  B  B  A
    2     A  A  A  A
    3     B  B  A  A
    4     B  C  A  A
    
         v1 v2 v3 v4
    cust            
    1     A  A  C  B
    2     A  A  C  B
    3     C  B  B  A
    4     C  B  B  A
    
    为了便于将来参考,为了便于再现示例,最好提供一些代码,这些代码可以由SO直接复制/粘贴,以便快速开始解决您的问题

    df1 = pd.read_csv(io.StringIO("""
    1 A B B A
    2 A A A A
    3 B B A A
    4 B C A A
    """), sep=' ', names='cust v1 v2 v3 v4'.split()).set_index('cust')
    
    df2 = pd.read_csv(io.StringIO("""
    1 A A C B
    2 A A C B
    3 C B B A
    4 C B B A
    """), sep=' ', names='cust v1 v2 v3 v4'.split()).set_index('cust')
    

    您可以将每个数据帧转换为一系列集合,然后利用以下系列执行集合操作:

    df2.apply(set, axis=1) - df1.apply(set, axis=1)
    
    输出:

    cust
    1       {C}
    2    {C, B}
    3       {C}
    4        {}
    dtype: object
    

    如果需要跨数据集(即集合中的元素或其他元素,但不是两者都有),则最好使用
    pd.concat

    dfs=[df1,df2]
    pd.concat([df.apply(set,1)用于dfs中的df],1).apply(lambda x:x[0]^x[1],1)
    
    其中1表示轴=1
    。另外,将
    x[0]^x[1]
    替换为
    set.symmetric\u difference(*x)
    也可以

    有趣的是,
    Series\u A^Series\u B
    并没有像预期的那样工作,相反(显然),它返回bool-Ser