【发布时间】:2022-02-04 09:42:41
【问题描述】:
在使用numpy.genfromtxt 从csv 文件加载简单距离矩阵时,我已经厌倦了等待。在另一个 SO question 之后,我执行了 perfplot 测试,同时包括了一些额外的方法。结果(源代码在最后):
最大输入大小的结果表明最佳方法是read_csv,即:
def load_read_csv(path: str):
with open(path, 'r') as csv_file:
reader = csv.reader(csv_file)
matrix = None
first_row = True
for row_index, row in enumerate(reader):
if first_row:
size = len(row)
matrix = np.zeros((size, size), dtype=int)
first_row = False
matrix[row_index] = row
return matrix
现在我怀疑逐行读取文件,将其转换为字符串列表,然后对列表中的每个项目调用 int() 并将其添加到 NumPy 矩阵中是最好的方法。
能否进一步优化此函数,或者是否有一些用于 CSV 加载的快速库(如 Java 中的 Univocity parser),或者可能只是一个专用的 NumPy 函数?
测试源码:
import perfplot
import csv
import numpy as np
import pandas as pd
def load_read_csv(path: str):
with open(path, 'r') as csv_file:
reader = csv.reader(csv_file)
matrix = None
first_row = True
for row_index, row in enumerate(reader):
if first_row:
size = len(row)
matrix = np.zeros((size, size), dtype=int)
first_row = False
# matrix[row_index] = [int(item) for item in row]
matrix[row_index] = row
return matrix
def load_loadtxt(path: str):
matrix = np.loadtxt(path, dtype=int, comments=None, delimiter=",", encoding="utf-8")
return matrix
def load_genfromtxt(path: str):
matrix = np.genfromtxt(path, dtype=int, comments=None, delimiter=",", deletechars=None, replace_space=None, encoding="utf-8")
return matrix
def load_pandas(path: str):
df = pd.read_csv(path, header=None, dtype=np.int32)
return df.values
def load_pandas_engine_pyarrow(path: str):
df = pd.read_csv(path, header=None, dtype=np.int32, engine='pyarrow')
return df.values
def load_pandas_engine_python(path: str):
df = pd.read_csv(path, header=None, dtype=np.int32, engine='python')
return df.values
def setup(n):
matrix = np.random.randint(0, 10000, size=(n, n), dtype=int)
filename = f"square_matrix_of_size_{n}.csv"
np.savetxt(filename, matrix, fmt="%d", delimiter=",")
return filename
b = perfplot.bench(
setup=setup, # or setup=np.random.rand
kernels=[
load_read_csv,
load_loadtxt,
load_genfromtxt,
load_pandas,
load_pandas_engine_pyarrow,
load_pandas_engine_python
],
n_range=[2 ** k for k in range(15)]
)
b.save("out.png")
b.show()
【问题讨论】:
-
我认为
load_read_csv有点作弊,因为它假定行数为size并预先分配所需的数组。其他方法不这样做。也许在没有load_read_csv的假设的情况下重复这个测试。 -
但是 dm 始终是方阵,所以我需要相反:我需要告诉其他方法来预先分配数组:)
-
我明白了。为了更清楚,我重新表述了这个问题。
-
如果有一个“专用的numpy函数”,你不认为前面的链接会提到它吗:(我最近探索了一个单列案例,stackoverflow.com/questions/70602007/…
标签: python numpy performance csv io