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