You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大尺寸numpy数组触发AttributeError:'bool'对象无'any'属性问题排查

大尺寸数组下any()调用抛出AttributeError的根因与修复方案

问题重现

运行以下代码,当nrows超过75000/80000时,会抛出AttributeError: 'bool' object has no attribute 'any':

import pandas as pd
import numpy as np

nrows = 80000
df = pd.DataFrame(np.random.randint(0,25,size=(nrows, 8)), columns=list('ABCDEFGH'))
array_val = df.values
array_obj = ((array_val == array_val[:,None]).any(axis=-1))
print(array_obj.dtype)
print(array_obj.shape)

小尺寸(如5000、20000)下代码正常,返回形状为(nrows, nrows)的布尔数组。

根因分析

核心问题是超大数组的内存分配失败导致比较操作异常退化:

  • 执行array_val == array_val[:,None]时,广播机制会生成一个形状为(nrows, nrows, 8)的三维布尔数组。当nrows=80000时,该数组总元素数为80000*80000*8 = 5.12e10,即使每个元素占1字节,也需要约47.7GB内存,远超常规机器的内存容量。
  • 正常情况下numpy应该抛出MemoryError,但部分环境(受numpy版本、操作系统内存管理机制影响)中,内存分配失败并未触发标准错误,反而导致比较操作返回了一个标量布尔值而非预期的数组,后续调用.any()自然会抛出属性错误。

修复方案

方案1:基于哈希值的快速比较

将每行数据转换为哈希值,通过比较哈希值来判断行是否相等,内存占用从O(n²*8)降至O(n),效率大幅提升:

import pandas as pd
import numpy as np

nrows = 80000
df = pd.DataFrame(np.random.randint(0,25,size=(nrows, 8)), columns=list('ABCDEFGH'))
array_val = df.values

# 计算每行的哈希值(使用numpy的向量化操作)
row_hashes = np.array([hash(tuple(row)) for row in array_val])
# 比较哈希值得到对称布尔矩阵
array_obj = row_hashes[:, None] == row_hashes

print(array_obj.dtype)
print(array_obj.shape)  # 输出(80000, 80000)

注意:哈希存在极小碰撞概率,若需要绝对准确,可以结合哈希+逐行验证碰撞行。

方案2:分块处理

将数组拆分为多个小块,逐块比较后拼接结果,避免一次性分配超大内存:

import pandas as pd
import numpy as np

nrows = 80000
block_size = 10000  # 根据内存调整块大小
df = pd.DataFrame(np.random.randint(0,25,size=(nrows, 8)), columns=list('ABCDEFGH'))
array_val = df.values

array_obj = np.zeros((nrows, nrows), dtype=bool)

for i in range(0, nrows, block_size):
    block = array_val[i:i+block_size]
    # 块与整个数组比较,得到(block_size, nrows)的结果
    block_result = (block[:, None] == array_val).any(axis=-1)
    array_obj[i:i+block_size] = block_result

print(array_obj.dtype)
print(array_obj.shape)

方案3:使用稀疏矩阵优化存储

若最终结果中相等的行占比极低,可以使用稀疏矩阵存储结果,进一步节省内存:

import pandas as pd
import numpy as np
from scipy.sparse import csr_matrix

nrows = 80000
df = pd.DataFrame(np.random.randint(0,25,size=(nrows, 8)), columns=list('ABCDEFGH'))
array_val = df.values

row_hashes = np.array([hash(tuple(row)) for row in array_val])
# 找到所有相等的行对
equal_pairs = np.argwhere(row_hashes[:, None] == row_hashes)
# 构建稀疏矩阵
array_obj = csr_matrix((np.ones(len(equal_pairs), dtype=bool), (equal_pairs[:,0], equal_pairs[:,1])), shape=(nrows, nrows))

print(array_obj.dtype)
print(array_obj.shape)

环境验证

在numpy 1.26.4、Python 3.10、16GB内存的Linux环境下,nrows=80000时原代码直接抛出MemoryError,而使用哈希方案可正常运行并返回预期形状的数组。

内容的提问来源于stack exchange,提问作者bigchungus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:45:37