问题描述
我有一个 dfs 列表,其中一些共享一个公共列 'b' 值。我按它们的 'b' 值对这些 dfs 进行分组,然后想比较其余列的任何差异。我需要直观地输出不同的列(而不仅仅是确定哪些列/行不同,我知道你可以用 pandas.testing assert_frame_equal 来做)。到目前为止,我是通过根据存储在列表中的 dfs 数量预先指定要运行的比较次数来实现的(如下面第三部分所示)。但我想这样做而不必指定要比较的 dfs 的数量,以防有更多的时间。
比较的替代方法可能是 .isin(使用 ~ 所以它不在?)或我正在寻找的反合并 rn。
非常欢迎所有评论。非常感谢!
数据
import pandas as pd
df1 = pd.DataFrame(data={'id': [1,2,3],'a': [1,'b': ['t1','t1','t1']})
df2 = pd.DataFrame(data={'id': [1,4],'a': [2,'t1']})
df3 = pd.DataFrame(data={'id': [1,'b': ['t2','t2','t2']})
df4 = pd.DataFrame(data={'id': [1,'b': ['t3','t3','t3']})
df5 = pd.DataFrame(data={'id': [1,'t1']})
df_lst=[df1,df2,df3,df4,df5]
根据“b”列中的组拆分为列表
from itertools import groupby
out = []
for _,g in groupby(
sorted(df_lst,key=lambda k: k["b"].tolist()),lambda k: k["b"].tolist()):
out.append(list(g))
比较存储在'out'中的dfs的列表(列表)中的每个df
for i in out:
if len(i) > 1:
a = (i[0].compare(i[1]))
b = (i[0].compare(i[2]))
c = (i[1].compare(i[2]))
lst=(a,b,c)
pd.concat(lst)
也许是这样的 但这仅将 0 与所有其他 dfs 进行比较,因此不起作用
for i in out:
if len(i)>1:
for j in range(len(i)):
a = i[0].compare(i[j])
o.append(a)
解决方法
以下内容应将 out
的每个条目与所有其他条目进行比较:
if all(isinstance(x,list) for x in out):
out_df = []
for entry in out:
out_df.append(pd.DataFrame(entry))
out = out_df
comp_list = []
for i,entry_1 in enumerate(out):
for j,entry_2 in enumerate(out):
if j > i:
comp = (entry_1.compare(entry_2))
comp_list.append(comp)
lst = tuple(comp_list)
pd.concat(lst)
编辑:我在代码段的开头添加了 if
语句以说明 out
存储列表而不是数据框的情况(就像您的拆分后的原始示例)。