我需要一次比较两个DataFrame,以找出值是否匹配。一个DataFrame来自Excel工作簿,另一个来自SQL查询。问题在于,不仅列可能不按顺序排列,而且列标题也可能具有不同的名称。这将阻止我简单地获取Excel列标题,并使用它们重新排列SQL DataFrame中的列。此外,我将在excel工作簿中的多个选项卡上针对不同的查询来执行此操作。列名称不仅在excel和SQL之间有所不同,而且在excel和excel之间以及SQL与SQL之间也可能有所不同。
我确实创建了一个解决方案,但是它不仅非常不稳定,而且我担心它将开始占用大量内存来运行。
解决方案需要使用列表中的列表。如果excel值与SQL值在同一列表中,则将它们视为匹配项,并且该函数将返回SQL DataFrame必须更改为与Excel DataFrame使用的相同顺序的最终顺序。如果我错过了一些可能,并且新创建的订单列表的长度与所需的长度不同,我只需按照原始顺序返回原始SQL标头列表即可。
以下示例仅是我实际使用的内容的一小部分。实际的变体数和列名比下面的示例高得多。任何人对如何改进此功能或为该问题提供更好的解决方案的任何建议,将不胜感激。
以下是示例:
#Example data
exceltab1 = {'ColA':[1,2,3],
'ColB':[3,4,1],
'ColC':[4,1,2]}
exceltab2 = {'cColumn':[10,15,17],
'aColumn':[5,7,8],
'bColumn':[9,8,7]}
sqltab1 = {'Col/A':[1,2,3],
'Col/C':[4,1,2],
'Col/B':[3,4,1]}
sqltab2 = {'col_banana':[9,8,7],
'col_apple':[5,7,8],
'col_carrot':[10,15,17]}
#Code
import pandas as pd
ec1 = pd.DataFrame(exceltab1)
ec2 = pd.DataFrame(exceltab2)
sq1 = pd.DataFrame(sqltab1)
sq2 = pd.DataFrame(sqltab2)
#This will fail because the columns are out of order
result1 = (ec1.values == sq1.values).all()
def translate(excel_headers ,sql_headers):
translator = [["ColA", "aColumn", "Col/A", "col_apple"],
["ColB", "bColumn", "Col/B", "col_banana"],
["ColC", "cColumn", "Col/C", "col_carrot"]]
order = []
for i in range(len(excel_headers)):
for list in translator:
for item in sql_headers:
if excel_headers[i] in list and item in list:
order.append(item)
break
if len(order) != len(sql_headers):
return sql_headers
else:
return order
sq1 =sq1[translate(list(ec1.columns), list(sq1.columns))]
#This will pass because the columns now line up
result2 = (ec1.values == sq1.values).all()
print(f"Result 1: {result1} , Result 2: {result2}")
结果: 结果1:错误,结果2:正确
答案 0 :(得分:0)
没有代码,而是一个算法。
我们有一组A列和另一个B列。我们可以比较A列和B列的比较,看它们是否相等。我们对所有列组合都执行此操作。
这可以看作是二部图,其中有两组顶点A和B(每列一个顶点),并且如果这两列相等,则在两个顶点之间存在边。那么转换列名的问题就等于在该二部图中找到了完美的匹配。
与此相关的算法是Hopkroft-Karp,它具有Python实现here。这样可以找到最大的匹配项,因此您仍然必须检查它是否找到了完美的匹配项(也就是说,A中的每一列都有B中的关联列)。