我正在努力比较(比较)2 个大型 CSV 文件。
例如:
文件1
a,b,c,d
e,f,g,h
i,j,k,l
文件2
a,b,c,d
i,j,k,l
e,f,g,h
上面应该是可以通过比较的,虽然行的顺序不一样,但是内容是一样的。
如果内容不同、列值不匹配、或者某一行存在于另一行中,等等,则比较应该失败。
我遇到的最大问题是文件非常大,并且没有可排序的键列。文件有 14 到 3000 万行,大约 10 到 15 列。未排序的原始数据转储约为 1GB 的 csv 文件。
现在我正在尝试使用下面的代码对文件进行排序和“比较”。问题是“排序”并不总是有效。对于较小的文件和较少的行,排序和比较可以工作,但它似乎不适用于非常大的文件。
此外,排序也会显着增加操作时间;理想情况下,我想避免排序,只是比较忽略排序顺序,但我不知道该怎么做。
filecmm、difflib 和我尝试过的其他一些功能都需要预先排序的文件。
我现在正在执行 Python 合并排序,但正如我所说,排序不一定适用于大量行,我希望有更好的比较方法。
这是Python的归并排序函数:
def batch_sort(self, input, output, key=None, buffer_size=32000, tempdirs=None):
if isinstance(tempdirs, str):
tempdirs = tempdirs.split(",")
if tempdirs is None:
tempdirs = []
if not tempdirs:
tempdirs.append(gettempdir())
chunks = []
try:
with open(input,'rb',64*1024) as input_file:
input_iterator = iter(input_file)
for tempdir in cycle(tempdirs):
current_chunk = list(islice(input_iterator,buffer_size))
if not current_chunk:
break
current_chunk.sort(key=key)
output_chunk = open(os.path.join(tempdir,'%06i'%len(chunks)),'w+b',64*1024)
chunks.append(output_chunk)
output_chunk.writelines(current_chunk)
output_chunk.flush()
output_chunk.seek(0)
with open(output,'wb',64*1024) as output_file:
output_file.writelines(self.merge(key, *chunks))
finally:
for chunk in chunks:
try:
chunk.close()
os.remove(chunk.name)
except Exception:
pass
我可以调用batch_sort(),给它一个输入文件和输出文件、块的大小以及要使用的临时目录。
一旦我对两个文件执行batch_sort(),我就可以“diff file1 file2”。
以上适用于 25,000 到 75,000 行,但当我们谈论超过 1400 万行时则不适用。
只需使用
set
并添加每一行。最后比较一下集合:
def compare(file1, file2):
with open(file1) as fh1, open(file2) as fh2:
left = {line for line in fh1}
right = {line for line in fh2}
return left == right
如果你真的很关心大小,你可以使用一个文件,而第二个文件中找不到第二行,你可以将其短路:
def compare(file1, file2):
with open(file1) as fh:
left = {line for line in fh}
right = set()
with open(file2) as fh:
for line in fh:
if line not in left:
return False
right.add(line)
return left == right
使用最低公分母算法不太可能起作用。 Big-Oh 表示法告诉您,读取、排序和比较这些操作至少需要 O(n),其中 n == 文件中的行数。
there is no key column to sort on
- 也许数据中没有自然键,但您应该能够为每一行生成一个哈希字符串并对其进行排序。如果您可以保证每行的哈希值都是唯一的,则不需要所有数据。然后你就可以对哈希列表进行操作了。
我看到的最大问题是要求两者同时存在于内存中。物理学说,当 X > Y 时,您无法将 X 放入 Y 容量的容器中。