我有一个包含三个以逗号分隔的值的大文本文件(> 1GB),我希望以块的形式读入Pandas DataFrame. DataFrame的一个示例如下:
我想在读取文件时过滤此文件并输出“干净”版本.我遇到的一个问题是某些时间戳是无序的,但问题通常是非常局部的(通常是在前后几个插槽中无序的滴答).有没有办法进行本地化的“滑动窗口”排序?
另外,由于我对Python很新,并且了解I / O方法,我不确定用于过滤大数据文件的最佳类/方法. TextIOBase?
最佳答案 这是一个非常有趣的问题,因为数据足够大,不容易适应内存.
首先,关于I / O:如果它是CSV,我会使用标准库csv.reader()
对象,就像这样(我假设Python 3):
with open('big.csv', newline='') as f:
for row in csv.reader(f):
...
然后我可能会在collections.deque(maxlen=WINDOW_SIZE)
实例中保留一个行的滑动窗口,窗口大小根据您的描述设置为20.将第一个WINDOW_SIZE行读入双端队列,然后进入主读取循环,该循环将输出双端队列中最左侧的项目(行),然后追加当前行.
在追加每一行之后,如果当前行的时间戳位于前一行(window [-2])的时间戳之前,则对deque进行排序.你不能直接对双端队列进行排序,但做的事情如下:
window = collections.deque(sorted(window), maxlen=WINDOW_SIZE)
Python的Timsort算法可以有效地处理已经排序的运行,所以这应该非常快(线性时间).
如果窗口大小和无序行的数量很小(听起来可能是这样),我相信整个算法将是O(N),其中N是数据文件中的行数,所以线性时间.
更新:我写了一些演示代码来生成这样的文件然后使用上面的技术对它进行排序 – 参见this Gist,在Python 3.5上测试.它比同一数据上的排序实用程序快得多,并且在大约N = 1,000,000之后也比Python的sorted()函数更快.顺便提一下,生成演示CSV的功能明显慢于排序代码. :-)我的结果计时process_sliding()为各种N(绝对看起来线性):
> N = 1,000,000:3.5s
> N = 2,000,000:6.6s
> N = 10,000,000:32.9s
作为参考,这是我的process_sliding()版本的代码:
def process_sliding(in_filename, out_filename, window_size=20):
with (open(in_filename, newline='') as fin,
open(out_filename, 'w', newline='') as fout):
reader = csv.reader(fin)
writer = csv.writer(fout)
first_window = sorted(next(reader) for _ in range(window_size))
window = collections.deque(first_window, maxlen=window_size)
for row in reader:
writer.writerow(window.popleft())
window.append(row)
if row[0] < window[-2][0]:
window = collections.deque(sorted(window), maxlen=window_size)
for row in window:
writer.writerow(row)