我正在处理相当大规模的数据。作为参考,给定样品将具有~75,000,000行和15,000-20,000列。
截至目前,为了节省内存,我采用了创建系列列表的方法(每列是一个系列,所以~15K-20K系列每个包含~250K行)。然后我创建一个包含这些系列中每个索引的SparseDataFrame(因为正如您所注意到的,这是一个很大但不是非常密集的数据集)。问题是这变得非常慢,并且将每列附加到数据集需要几分钟。为了克服这个问题,我也尝试了对合并进行批处理(选择数据的一个子集,将它们合并到一个DataFrame,然后合并到我的主DataFrame中),但这种方法仍然太慢。缓慢意味着它每天仅处理~4000列,每次追加都会导致后续追加时间更长。
让我感到奇怪的一个部分是为什么我的主DataFrame的列数会影响追加速度。因为我的主索引已经包含它将看到的所有条目,所以我不应该因为重新索引而浪费时间。
无论如何,这是我的代码:
import time
import sys
import numpy as np
import pandas as pd
precision = 6
df = []
for index, i in enumerate(raw):
if i is None:
break
if index%1000 == 0:
sys.stderr.write('Processed %s...\n' % index)
df.append(pd.Series(dict([(np.round(mz, precision),int(intensity)) for mz, intensity in i.scans]), dtype='uint16', name=i.rt))
all_indices = set([])
for j in df:
all_indices |= set(j.index.tolist())
print len(all_indices)
t = time.time()
main_df = pd.DataFrame(index=all_indices)
first = True
del all_indices
while df:
subset = [df.pop() for i in xrange(10) if df]
all_indices = set([])
for j in subset:
all_indices |= set(j.index.tolist())
df2 = pd.DataFrame(index=all_indices)
df2.sort_index(inplace=True, axis=0)
df2.sort_index(inplace=True, axis=1)
del all_indices
ind=0
while subset:
t2 = time.time()
ind+=1
arr = subset.pop()
df2[arr.name] = arr
print ind,time.time()-t,time.time()-t2
df2.reindex(main_df.index)
t2 = time.time()
for i in df2.columns:
main_df[i] = df2[i]
if first:
main_df = main_df.to_sparse()
first = False
print 'join time', time.time()-t,time.time()-t2
print len(df), 'entries remain'
关于如何快速加载这个大型数据集的任何建议都值得赞赏,即使这意味着首先将其写入磁盘到其他格式/等等。
其他一些信息:
1)由于列数,我无法使用大多数传统的磁盘存储,如HDF。
2)数据将在使用时跨列和行进行查询。所以main_df.loc [row:row_end,col:col_end]。这些不是可预测的块大小,因此分块实际上不是一种选择。这些查找也需要很快,大约每秒10次,才能真正有用。
3)我有32G的内存,所以我认为SparseDataFrame是最好的选择,因为它适合内存并允许根据需要快速查找。只是创造它是一种痛苦。
更新
我最终使用scipy稀疏矩阵并暂时处理索引。这导致以~0.2秒的恒定速率附加,这是可接受的(相对于Pandas每次追加我的完整数据集需要约150秒)。我很想知道如何让Pandas与这种速度相匹配。