我编写了一堆代码,假设我将使用 Numpy 数组。结果我得到的数据是通过 Pandas 加载的。我现在记得我将它加载到 Pandas 中,因为我在 Numpy 中加载它时遇到了一些问题。我认为数据太大了。
因此我想知道,使用 Numpy 和 Pandas 时计算能力有区别吗?
如果 Pandas 更高效,那么我宁愿为 Pandas 重写所有代码,但如果没有更高的效率,那么我只会使用 numpy 数组...
可能存在显着的性能差异,乘法有一个数量级,索引一些随机值有多个数量级。
我实际上也想知道同样的事情,并发现了这个有趣的比较: http://penandpants.com/2014/09/05/performance-of-pandas-series-vs-numpy-arrays/
我认为更多的是根据您看到的性能战略性地使用这两者并转移数据(从 numpy 到 pandas 或反之亦然)。作为最近的示例,我尝试使用 numpy 连接 4 个小 pickle 文件,每个文件有 10k 行
data.shape -> (10,000, 4)
。
代码类似于:
n_concat = np.empty((0,4))
for file_path in glob.glob('data/0*', recursive=False):
n_data = joblib.load(file_path)
n_concat = np.vstack((co_np, filtered_snp))
joblib.dump(co_np, 'data/save_file.pkl', compress = True)
这让我的笔记本电脑(8 GB,i5)崩溃了,这很令人惊讶,因为体积并不是那么大。 4 个压缩的 pickled 文件每个大约 5 MB 左右。 同样的事情,在熊猫上效果很好。
for file_path in glob.glob('data/0*', recursive=False):
n_data = joblib.load(sd)
try:
df = pd.concat([df, pd.DataFrame(n_data, columns = [...])])
except NameError:
df = pd.concat([pd.DataFrame(n_data,columns = [...])])
joblib.dump(df, 'data/save_file.pkl', compress = True)
另一方面,当我通过迭代 pandas 数据框来实现梯度下降时,速度非常慢,而使用 numpy 来完成这项工作要快得多。
总的来说,我发现 pandas 通常更适合移动/咀嚼中等大的数据块并执行常见的列操作,而 numpy 最适合在较小的数据集上进行矢量化和递归工作(可能是更数学密集的工作)。
在两者之间移动数据是没有麻烦的,所以我想,策略性地使用两者是正确的方法。
。这是一个巨大的差异,因为只执行了简单的算术运算:列切片、mean()、searchsorted() - 见下文。最初,我认为 Pandas 是基于 numpy 的,或者至少它的实现是 C 优化的,就像 numpy 的一样。然而,考虑到巨大的性能差距,这些假设被证明是错误的。 在下面的示例中,
data
是一个具有 8M 行和 3 列(int32、float32、float32)的 pandas 框架,没有 NaN 值,第 0 列(时间)已排序。
data_np
被创建为 data.values.astype('float32')
。 Python 3.8、Ubuntu 上的结果:A。列切片和mean():
# Pandas
%%timeit
x = data.x
for k in range(100): x[100000:100001+k*100].mean()
15.8 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# Numpy
%%timeit
for k in range(100): data_np[100000:100001+k*100,1].mean()
874 µs ± 4.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Pandas 比 Numpy 慢 18 倍(15.8 毫秒 vs 0.874 毫秒)。B.在排序列中搜索:
# Pandas
%timeit data.time.searchsorted(1492474643)
20.4 µs ± 920 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# Numpy
%timeit data_np[0].searchsorted(1492474643)
1.03 µs ± 3.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Pandas 比 Numpy 慢 20 倍(20.4μs vs 1.03μs)。编辑:
我实现了一个命名数组类,它弥补了 Pandas 和 Numpy 之间的差距,因为它基于 Numpy 的 ndarray 类,因此性能比 Pandas 更好(通常快 7 倍),并且与 Numpy'a API 和所有内容完全兼容其运营商;但同时它保持列名称类似于 Pandas 的 DataFrame,因此对各个列的操作更容易。这是一个原型实现。与 Pandas 不同,namedarray not 允许列使用不同的数据类型。代码可以在这里找到:https://github.com/mwojnars/nifty/blob/master/math.py(搜索“namedarray”)。
# The pandas function
def make_data(dataframe: pd.DataFrame, ws: int) -> Tuple[List, List]:
features = [dataframe.iloc[i:i+ws, :-1].values for i in range(len(dataframe) - ws)]
targets = [dataframe.iloc[i+ws, -1] for i in range(len(dataframe) - ws)]
return features, targets
start_time = time.time()
features, targets = make_data(arranged_dataframe, ws=ws)
end_time = time.time()
print(f"Time taken: {end_time - start_time} seconds")
# the numpy function
def make_data(dataframe: pd.DataFrame, ws: int) -> Tuple[np.ndarray, np.ndarray]:
data = dataframe.to_numpy()
num_samples = len(data) - ws
features = np.empty((num_samples, ws, data.shape[1]), dtype=data.dtype)
targets = np.empty(num_samples, dtype=data.dtype)
for i in range(num_samples):
features[i] = data[i:i+ws, ]
targets[i] = data[i+ws, -1]
return features, targets
start_time = time.time()
features, targets = make_data(arranged_dataframe, ws=16)
end_time = time.time()
print(f"Time taken: {end_time - start_time} seconds")
输出:
Time taken: 0.25033116340637207 seconds
Time taken: 1020.9403311634064 seconds