如何在Python中使用贪婪方法对两个数据帧中最相似的列进行配对

如何在Python中使用贪婪方法对两个数据帧中最相似的列进行配对,python,pandas,Python,Pandas,我有两个24x10大小的数据帧(虽然实际的df大小很大)。通过枚举df1中的列并查找df2中最相似(不一定完全相同)的列,需要以贪婪的方式对所有列进行配对。结果将生成df1的每一列的一对,并与df2中的一个未分配列配对。dfs如下所示 df1 = pd.DataFrame([[1., 1., 1., 1., 1., 1., 0., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.], [1., 1., 1., 1., 1., 1

我有两个24x10大小的数据帧(虽然实际的df大小很大)。通过枚举df1中的列并查找df2中最相似(不一定完全相同)的列,需要以贪婪的方式对所有列进行配对。结果将生成df1的每一列的一对,并与df2中的一个未分配列配对。dfs如下所示

df1 = pd.DataFrame([[1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 0.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 2., 1., 1., 1., 0., 1., 1., 0.],
   [2., 1., 1., 3., 1., 1., 0., 1., 1., 1.],
   [2., 1., 1., 2., 1., 1., 1., 1., 1., 0.],
   [2., 1., 1., 3., 1., 1., 1., 1., 1., 0.],
   [2., 1., 1., 3., 1., 2., 1., 1., 1., 0.],
   [2., 1., 1., 4., 2., 2., 1., 1., 1., 1.],
   [2., 4., 1., 4., 3., 1., 1., 1., 1., 1.],
   [2., 4., 1., 4., 3., 1., 1., 1., 1., 1.],
   [2., 4., 1., 5., 2., 1., 0., 1., 1., 1.],
   [2., 4., 1., 6., 2., 1., 0., 1., 1., 1.],
   [2., 4., 1., 5., 2., 1., 1., 1., 1., 1.],
   [2., 4., 1., 5., 1., 1., 0., 1., 1., 1.],
   [2., 4., 1., 5., 3., 1., 1., 1., 1., 1.],
   [1., 4., 1., 4., 2., 1., 1., 1., 1., 1.],
   [1., 4., 2., 4., 2., 1., 1., 1., 1., 1.],
   [1., 1., 2., 3., 2., 1., 1., 1., 1., 1.],
   [1., 1., 2., 1., 2., 1., 1., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.]])

df2 = pd.DataFrame([[0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 0., 0., 1., 1., 1., 1., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [0., 0., 1., 1., 1., 1., 1., 0., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 1., 0., 0., 0., 1.],
   [0., 1., 1., 1., 0., 0., 1., 1., 1., 1.],
   [0., 0., 1., 1., 1., 1., 0., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [1., 1., 1., 1., 0., 0., 0., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 0., 0., 0., 1., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 1., 0., 0., 0., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.]] )
for key1, value1 in df1.iteritems():
#print(value)
    for key2, value2 in df2.iteritems():
        common_elements = [e for e in list(value1) if e in list(value2)]
    l = len(common_elements)
    
“最相似”可以定义为列之间公共元素的最大数量。任何帮助或线索都值得赞赏。 我试了以下方法

df1 = pd.DataFrame([[1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 0.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 2., 1., 1., 1., 0., 1., 1., 0.],
   [2., 1., 1., 3., 1., 1., 0., 1., 1., 1.],
   [2., 1., 1., 2., 1., 1., 1., 1., 1., 0.],
   [2., 1., 1., 3., 1., 1., 1., 1., 1., 0.],
   [2., 1., 1., 3., 1., 2., 1., 1., 1., 0.],
   [2., 1., 1., 4., 2., 2., 1., 1., 1., 1.],
   [2., 4., 1., 4., 3., 1., 1., 1., 1., 1.],
   [2., 4., 1., 4., 3., 1., 1., 1., 1., 1.],
   [2., 4., 1., 5., 2., 1., 0., 1., 1., 1.],
   [2., 4., 1., 6., 2., 1., 0., 1., 1., 1.],
   [2., 4., 1., 5., 2., 1., 1., 1., 1., 1.],
   [2., 4., 1., 5., 1., 1., 0., 1., 1., 1.],
   [2., 4., 1., 5., 3., 1., 1., 1., 1., 1.],
   [1., 4., 1., 4., 2., 1., 1., 1., 1., 1.],
   [1., 4., 2., 4., 2., 1., 1., 1., 1., 1.],
   [1., 1., 2., 3., 2., 1., 1., 1., 1., 1.],
   [1., 1., 2., 1., 2., 1., 1., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.],
   [1., 1., 1., 1., 1., 1., 0., 1., 1., 1.]])

df2 = pd.DataFrame([[0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 0., 0., 1., 1., 1., 1., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [0., 0., 1., 1., 1., 1., 1., 0., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 0., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 1., 0., 0., 0., 1.],
   [0., 1., 1., 1., 0., 0., 1., 1., 1., 1.],
   [0., 0., 1., 1., 1., 1., 0., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 0., 0., 1., 1.],
   [1., 1., 1., 1., 0., 0., 0., 1., 1., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 0., 0., 0., 1., 1.],
   [0., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
   [1., 1., 1., 1., 1., 1., 0., 0., 0., 1.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.],
   [0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
   [0., 0., 1., 1., 1., 1., 1., 1., 1., 0.]] )
for key1, value1 in df1.iteritems():
#print(value)
    for key2, value2 in df2.iteritems():
        common_elements = [e for e in list(value1) if e in list(value2)]
    l = len(common_elements)
    

这是比赛的一种方式

假设:

#1:如果df1中的一列与df2中的一列匹配,则两列将被删除以进行进一步匹配。 例如,如果df1中的列1和列3与df2中的列5完全匹配,则只有df1中的列1将与df2中的列5配对。df1中的第3列需要寻找新的匹配项

#2:df1和df2将有相同数量的行进行比较。对于本例,我还考虑行和列的大小相同。对代码的细微调整可以解决列中的差异,但行计数必须匹配

#3:列比较必须精确匹配。换句话说,如果第1列第1行在df1中的值为1,则df2的第1列第1行应为1。如果是,则不会重新排列行和列上的匹配数据以检查df1或df2中的匹配

根据上述假设,代码如下所示

#create a list to store all the match counts
df_list = []

#iterate through df1 first
for cols1 in df1.columns:

    #convert df1 column value to a list
    x = df1[cols1].tolist()

    #iterate through df2 to match to df1 column data
    for cols2 in df2.columns:

        #convert df2 column value to a list
        y = df2[cols2].tolist()

        #iterate and compare each value in df1[col1] with df2[col2]
        #i==j will result in True or False
        #sum() will count all True values (i.e., all matched values)

        z = sum((i==j) for i,j in zip(x,y))

        #store match count, col 1, col 2 into the lsit
        df_list.append((z,cols1,cols2))

#once you have iterated through df2 for each df1
#sort the df_list by descending order of match count, ascending order of df1 column
#highest match will be first, then df1 column
df_list = sorted(df_list,key=lambda x:(-x[0],x[1]))

dfc1,dfc2,points = [],[],[]

#iterate thru df_list and pick only if df1 column and df2 column were not picked earlier
#dfc1, dfc2, points will store each matched pair

for p,c1,c2 in df_list:
    if (c1 not in dfc1) and (c2 not in dfc2):
        points.append(p)
        dfc1.append(c1)
        dfc2.append(c2)

#print the matched values

for i in range(len(dfc1)):
    print (f'{points[i]:2} rows of df1[{dfc1[i]}] matches with df2[{dfc2[i]}]')
输入数据帧df1和df2的输出为:

24 rows of df1[7] matches with df2[3]
23 rows of df1[8] matches with df2[2]
20 rows of df1[5] matches with df2[4]
18 rows of df1[2] matches with df2[5]
17 rows of df1[6] matches with df2[9]
15 rows of df1[9] matches with df2[1]
12 rows of df1[1] matches with df2[6]
 9 rows of df1[4] matches with df2[7]
 5 rows of df1[0] matches with df2[8]
 1 rows of df1[3] matches with df2[0]

你可以决定截止时间(EX:考虑比赛15或以上)。我们可以在将数据添加到列表之前添加过滤器。

您能详细说明一下“最相似”的含义吗?这是列的总和吗?是每列的行中的值吗?请提供预期结果和/或详细说明“最相似”。请浏览、和,了解本网站的工作原理,并帮助您改进当前和未来的问题,从而帮助您获得更好的答案。“演示如何解决此编码问题?”与堆栈溢出无关。您必须诚实地尝试解决方案,然后询问有关实现的特定问题。堆栈溢出不是为了取代现有的教程和文档。我不会投票结束这个问题。按照@Simon的要求,提供更多信息。如果你对它进行阐述,这是一个好的、高质量的问题。df1中的一列应该只与df2中的一列配对吗?对于EX:DF1中的第8列和第9列与DF2中的列4相匹配。是否有人告诉我,如果只考虑假设3,我如何调整代码?您可以在两边按升序排序数据。然后比较它们是否匹配。让我添加代码并与您分享。总之,我将在
x=df1[cols1].tolist()之后对
x
进行排序,并在
y=df2[cols2].tolist()之后对
y
进行排序。然后进行比较。通过这种方式,我以相同的顺序比较值,但在我的数据中,顺序很重要。行指的是时间步,所以我认为重新排序行会影响我的结果。实际上,我想要所有列的实际相交总数(按行)。我的解决方案已经保持了行顺序。该解决方案确保行匹配。你想要什么?保持行完整或忽略行顺序?保持行完整