在Python中比较两个不同来源的大型数据集的最佳方法是什么?

在Python中比较两个不同来源的大型数据集的最佳方法是什么?,python,pandas,Python,Pandas,我有两个来源的大型数据集,一个是巨大的csv文件,另一个来自数据库查询。我正在编写一个验证脚本来比较两个来源的数据,并记录/打印差异。我认为值得一提的是,来自这两个来源的数据的格式或顺序并不完全相同。例如: 源1(CSV文件): 资料来源2(数据库): 电子邮件键1键2键3 email1@gmail.com 1 1 5 email2@gmail.com 3 2 email4@gmail.com 1

我有两个来源的大型数据集,一个是巨大的csv文件,另一个来自数据库查询。我正在编写一个验证脚本来比较两个来源的数据,并记录/打印差异。我认为值得一提的是,来自这两个来源的数据的格式或顺序并不完全相同。例如:

源1(CSV文件):

资料来源2(数据库):

电子邮件键1键2键3
email1@gmail.com      1        1       5
email2@gmail.com      3        2       
email4@gmail.com      1        1       5
我想要的脚本的输出类似于:

source1 - source2 (or csv - db):  2 rows total with differences
email2@gmail.com      3        2       2
email3@gmail.com      <null>   3       1

source2 - source1 (or db-csv):  2 rows total with differences
email2@gmail.com      3        2       <null>
email4@gmail.com      1        1       5
source1-source2(或csv-db):共2行,有差异
email2@gmail.com      3        2       2
email3@gmail.com         3       1
source2-source1(或db csv):共2行,有差异
email2@gmail.com      3        2       
email4@gmail.com      1        1       5
输出格式可以稍有不同,以更清晰地显示更多差异(从数千条/数百万条记录中)

我开始编写脚本,将两个源中的数据保存到两个字典中,并循环遍历字典或从字典中创建集,但这似乎是一个非常低效的过程。我考虑过使用pandas,但pandas似乎没有办法对数据帧进行这种类型的比较


请告诉我是否有更好/更有效的方法。提前谢谢

您可以使用
pivot
转换df,在
concat

df2=df2.applymap(lambda x : pd.to_numeric(x,errors='ignore')
pd.concat([df.pivot(*df.columns).reset_index(),df2)],keys=['db','csv']).\
  drop_duplicates(keep=False).\
     reset_index(level=0).\
       rename(columns={'level_0':'source'})
Out[261]: 
key source             email  key1  key2    key3
1       db  email2@gmail.com     3     2       2
1      csv  email2@gmail.com     3     2  <null>
df2=df2.applymap(lambda x:pd.to_numeric(x,errors='ignore'))
pd.concat([df.pivot(*df.columns.reset_index(),df2)],键=['db','csv'])\
删除重复项(保留=False)\
重置索引(级别=0)\
重命名(列={'level_0':'source'})
Out[261]:
密钥源电子邮件密钥1密钥2密钥3
1分贝email2@gmail.com     3     2       2
1 csvemail2@gmail.com     3     2  

注意,这里我使用
to_numeric
将您的df2转换为numeric

您的路径是正确的。您想要的是快速匹配这两个表。熊猫可能是杀伤力过大了

您可能希望遍历第一个表并创建一个字典。您不想做的是为每个元素交互两个列表。即使是很小的列表也需要大量的搜索

该模块是从磁盘读取数据的好模块。对于每一行,您将把它放在字典中,其中键是电子邮件,值是完整的行。在一台普通的台式计算机上,你可以在一秒钟内迭代1000万行

现在,您将迭代抛出第二行,对于每一行,您将使用电子邮件从字典中获取数据。这样,因为dict是一个数据结构,您可以在O(1)中获得键值,所以您将通过N+M行进行交互。几秒钟后,您应该能够比较两个表。这真的很简单。下面是一个示例代码:

import csv
firstTable = {}
with open('firstTable.csv', 'r') as csvfile:
     reader = csv.reader(csvfile, delimiter=',')
        for row in reader:
            firstTable[row[0]] = row #email is in row[0]

for row2 in get_db_table2():
    email = row2[0]
    row1 = firstTable[email] #this is a hash. The access is very quick
    my_complex_comparison_func(row1, row2)
如果没有足够的RAM内存来容纳内存中第一个字典的所有键,则可以使用for the firstTable变量。这将在磁盘中创建一个索引,访问速度非常快


因为您的一个表已经在数据库中,所以我首先要做的可能是使用您的数据库将磁盘中的数据加载到一个临时表中。创建一个索引,并对表进行内部联接(如果需要知道哪些行在另一个表中没有数据,则进行外部联接)。数据库针对这种操作进行了优化。然后,您可以从python中进行选择以获得连接的行,并将python用于复杂的比较逻辑

谢谢@neves。我还考虑过将它加载到一个临时表中,但我不想在实际的数据库中这样做。因此,我考虑在本地sqlite表中执行此操作,但为了使连接工作,我必须将数据从实际的postgres数据库加载到sqlite db中,因此我认为来回数据传输太多。或者您认为将所有内容加载到本地sqlite db中仍然是一个好主意吗?@siddardha,这并不是真的必要。我描述的方法可能已经足够好了。使用电子邮件作为键将数据加载到字典后,您将很快匹配它。如果你需要更多的帮助,请写信给我。
df2=df2.applymap(lambda x : pd.to_numeric(x,errors='ignore')
pd.concat([df.pivot(*df.columns).reset_index(),df2)],keys=['db','csv']).\
  drop_duplicates(keep=False).\
     reset_index(level=0).\
       rename(columns={'level_0':'source'})
Out[261]: 
key source             email  key1  key2    key3
1       db  email2@gmail.com     3     2       2
1      csv  email2@gmail.com     3     2  <null>
import csv
firstTable = {}
with open('firstTable.csv', 'r') as csvfile:
     reader = csv.reader(csvfile, delimiter=',')
        for row in reader:
            firstTable[row[0]] = row #email is in row[0]

for row2 in get_db_table2():
    email = row2[0]
    row1 = firstTable[email] #this is a hash. The access is very quick
    my_complex_comparison_func(row1, row2)