从大文本文件到稀疏矩阵的Python实现

4 投票
2 回答
3492 浏览
提问于 2025-04-18 01:10

我正在寻找一种高效的方法来读取一个非常大的文本文件(大约有2,000,000行)。其中大约90%的行(实际上是最后的90%)是三列格式,用于存储稀疏矩阵。

这是我所做的。首先,我处理文件的前10%:

i=1
cpt=0
skip=0
finnum=0
indice=1 
vec=[]
mat=[]
for line in fileinput.input("MY_TEXT_FILE.TXT"):
if i==1:
    # skipping the first line
    skip = 1
if (finnum == 0)and(skip==0):
    # special reading operation for the first 10% (approximately)
    tline=shlex.split(line)
    ind_loc=0
    while ind_loc<len(tline):
    if (int(tline[ind_loc])!=0):
            vec.append(int(tline[ind_loc]))
        ind_loc=ind_loc+1   
if (finnum == 1)and(skip==0):
    print('finnum = 1')
    h=input()    
        break       
    if (' 0' in line):
    finnum = 1
if skip == 0:
    i=i+1
else:
    skip=0
    i=i+1
cpt=cpt+1

然后我把剩下的90%提取到一个列表中:

matrix=[]
with open('MY_TEXT_FILE.TXT') as f:
for i in range(cpt):
    f.next()
for line in f:
    matrix.append(line)

这样可以非常快速地读取文本文件,并且内存消耗很低。缺点是matrix是一个字符串列表,每个字符串看起来像:

>>> matrix[23]
'           5          11  8.320234929063493E-008\n'

我尝试使用一个迭代的方法来处理matrix中的每一行,并结合shlex.split命令将字符串列表转换为数组,但这非常耗时。

你知道有什么快速的方法可以将字符串列表转换为数组吗?

我想知道是否有比这个过程更快的方法:

A=[0]*len(matrix)
B=[0]*len(matrix)
C=[0]*len(matrix)
for i in range(len(matrix)):
     line = shlex.split(matrix[i])
     A[i]=float(line[0])
     B[i]=float(line[1])
     C[i]=float(line[2])

阿兰

2 个回答

2

当你在处理大量数字数据时,建议使用Numpy,而不是纯粹用Python。这样通常会快十倍以上,还能让你进行一些复杂的计算,类似于Matlab的功能。我现在没时间把你的代码转换过来(而且如果有个示例文件会更简单),但可以肯定的是,使用numpy.loadtxt可以快速高效地读取你文件的第二部分。你跳过第一部分并转换为浮点数的整个过程,可能可以用下面这样的代码来完成:

A, B, C = np.loadtxt('MY_TEXT_FILE.TXT', skiprows = cpt, unpack = True)

你可能需要调整一下数据格式(比如添加dtype = (int, int, float)之类的,我不太确定具体怎么做),因为我猜前两列是整数。

另外,注意Numpy还有一种叫做稀疏矩阵的数据类型可以使用。

2

听着,我想出了一个混合的解决方案,效果似乎快得多。我生成了100万个随机数据样本,就像你提到的那种,然后测试了你的代码。在我这台超级快的Mac电脑上,运行你的代码花了77秒。

使用numpy来分割字符串,而不是用shlex,处理时间缩短到了5秒。

A=[0]*len(matrix)
B=[0]*len(matrix)
C=[0]*len(matrix)
for i in range(len(matrix)):
    full_array = np.fromstring(matrix[i], dtype=float, sep=" ")
    A[i]=full_array[0]
    B[i]=full_array[1]
    C[i]=full_array[2]

我做了几次测试,结果看起来不错,速度快了14倍。希望这对你有帮助。

撰写回答