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

如何高效统计二维NumPy数组中二进制编码向量的出现频率?

高效统计大规模二进制向量出现频率的方法

问题描述

我有一个存储大量二进制编码向量的二维NumPy数组(示例如下,实际单向量元素数超8000,总向量数超58000):

import numpy as np
labels = np.array([
    [0, 1, 0, 0, 1, 0],
    [0, 0, 1, 0, 0, 1],
    [0, 1, 0, 0, 1, 0]
])

我需要统计每个完整向量的出现频率(示例的频率表应为[2,1]),类似Scipy的itemfreq或NumPy的histogram但针对整个向量。我自己写了一段双重循环的代码,虽然能运行,但数据量大时效率极低:

def get_label_set_freq_table(labels):
    uniques = np.empty_like(labels)
    freq_table = np.zeros(shape=labels.shape[0])
    equal = False
    for idx,row in enumerate(labels):
        for lbl_idx,label_set in enumerate(uniques):
            if np.array_equal(row,label_set):
                equal = True
                freq_table[lbl_idx] += 1
                break
        if not equal:
            uniques[idx] = row
            freq_table[idx] += 1
            equal = False
    return freq_table

求更高效的实现方式?


解决方案

你的代码用双重循环逐行比对,时间复杂度是O(n²),数据量到5万+的时候肯定会卡顿。核心优化思路是把每个向量转换成可快速哈希、比较的唯一标识,用哈希表或NumPy向量化操作来统计,把时间复杂度降到**O(n)**级别。以下是几种实用的高效方法:

方法1:Python原生collections.Counter(直观易实现)

把每个NumPy行向量转成不可变的元组(元组可作为字典键),然后用Counter直接计数:

import numpy as np
from collections import Counter

def fast_freq_counter(labels):
    # 生成元组序列(内存友好的生成器)
    tuple_rows = (tuple(row) for row in labels)
    # 统计频率
    count_dict = Counter(tuple_rows)
    # 转换成你需要的格式:唯一向量数组 + 频率数组
    unique_vectors = np.array(list(count_dict.keys()))
    freq_table = np.array(list(count_dict.values()))
    return unique_vectors, freq_table

这个方法比双重循环快几个数量级,适合中等规模的数据,代码也容易理解。

方法2:NumPyview二进制转整数(最优解,适合二进制向量)

因为你的向量是二进制的,我们可以把每个向量当成二进制数转成整数(或大整数块),用NumPy的unique直接统计:

import numpy as np

def binary_vector_freq(labels):
    # 把二进制向量转成连续的整数块(这里用uint64,可根据向量长度调整类型)
    # view操作是零拷贝,效率极高
    as_integers = labels.view(np.uint64).reshape(labels.shape[0], -1)
    # 用np.unique统计唯一值和频率
    unique_integers, freq_table = np.unique(as_integers, axis=0, return_counts=True)
    # 可选:还原回原始二进制向量
    unique_vectors = unique_integers.view(labels.dtype).reshape(unique_integers.shape[0], labels.shape[1])
    return unique_vectors, freq_table

这是最快的方法,完全用NumPy向量化操作,没有Python循环。如果向量长度超过单个整数类型的位数(比如uint64是64位),可以把向量分成多个块转成整数元组,再用np.unique处理。

方法3:Pandasvalue_counts(适合已有Pandas栈的场景)

如果你的项目已经在使用Pandas,直接把数组转成DataFrame用value_counts统计:

import numpy as np
import pandas as pd

def pandas_freq_counter(labels):
    df = pd.DataFrame(labels)
    freq_series = df.value_counts()
    # 转换成需要的格式
    unique_vectors = freq_series.index.to_numpy()
    freq_table = freq_series.values
    return unique_vectors, freq_table

Pandas的value_counts底层做了优化,效率和Counter相近,代码简洁。


性能总结

方法时间复杂度适用场景
原始双重循环O(n²)极小数据量(不推荐)
Counter元组法O(n)中等规模数据,易实现
NumPy view整数法O(n)大规模二进制向量,性能最优
Pandas value_countsO(n)已有Pandas栈的项目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:18:44