本文深入探讨如何在numpy中高效解决一个复杂的数据查询问题:为大型数组中的每一行,查找满足特定多列(第二列和第四列)值完全匹配,且在另一列(第一列)上距离最近的n个行的原始索引。通过摒弃低效的python for循环,本教程将详细展示如何利用numpy的向量化操作,包括数据预处理、巧妙的分块策略、广播机制进行距离计算与排序,以及结果整合与还原,从而实现显著的性能提升和代码的简洁性,为处理大规模数据集提供一个专业且可复用的解决方案。
在数据分析和科学计算中,我们经常需要从大型数据集中检索满足特定条件的记录。一个常见的挑战是,当查询条件涉及多列,并且需要根据某一列的“距离”来找出最接近的N个记录时,传统的逐行迭代(例如使用Python的for循环)会带来严重的性能问题,尤其是在处理百万级别甚至更大规模的NumPy数组时。
具体而言,我们的目标是:给定一个具有8列的NumPy数组,对于数组中的每一行,我们需要找出其他满足以下两个条件的N行:
最终输出应是一个与原始数组行数相同、列数为N的数组,其中每一行包含对应原始行的N个最近邻行的原始索引。
为了克服for循环的性能瓶颈,我们将采用NumPy的向量化能力。核心思路是:
在进行任何可能改变行顺序的操作之前,我们需要为原始数组的每一行添加一个唯一的标识符,即其在原始数组中的索引。这确保了即使数据经过排序、过滤和分块,我们也能最终追溯到其在原始数据集中的位置。
import numpy as np
# 假设 arr 是从 "data.txt" 加载的原始大型数组
# arr = np.loadtxt("data.txt")
# 示例数据(简化版,模拟原始数据结构)
# 假设原始数据有8列,这里只用4列进行演示
arr = np.array([
[1.0, 0.0, -1.6, 2.3], # idx 0
[1.0, 1.0, -1.6, 2.3], # idx 1
[1.0, 0.0, -1.6, 2.3], # idx 2 (col1=0, col4=2.3, col0=1.0)
[2.0, 0.0, -1.6, 2.3], # idx 3
[1.1, 0.0, -1.6, 2.3], # idx 4 (col1=0, col4=2.3, col0=1.1)
[1.2, 0.0, -1.6, 2.3], # idx 5 (col1=0, col4=2.3, col0=1.2)
[1.0, 1.0, -1.6, 2.3], # idx 6 (col1=1, col4=2.3, col0=1.0)
[1.1, 1.0, -1.6, 2.3], # idx 7 (col1=1, col4=2.3, col0=1.1)
[1.0, 0.0, -1.6, 7.3], # idx 8 (col1=0, col4=7.3, col0=1.0)
[1.1, 0.0, -1.6, 7.3] # idx 9 (col1=0, col4=7.3, col0=1.1)
])
# 添加原始索引作为最后一列
# np.c_ 用于按列堆叠数组
arr_indexed = np.c_[arr, np.arange(len(arr))]
print("原始数组(带索引):\n", arr_indexed)在上述代码中,np.arange(len(arr)) 生成一个从0到 len(arr)-1 的整数序列,然后 np.c_ 将其作为新的一列添加到原始数组 arr 的右侧。
为了高效处理“第二列和第四列值相同”的条件,我们可以首先对数组进行排序。选择第二列(索引为1)作为主要的排序键,因为它的值在问题描述中是离散的。排序后,所有第二列值相同的行将聚集在一起,这为后续的分块操作提供了便利。
# 按第二列的值进行排序
arr_sorted_by_col1 = arr_indexed[arr_indexed[:, 1].argsort()]
print("\n按第二列排序后的数组:\n", arr_sorted_by_col1)
# 根据第二列的唯一值进行分块
# np.unique(..., return_index=True) 返回唯一值及其首次出现的索引
unique_col1_values, split_indices = np.unique(arr_sorted_by_col1[:, 1], return_index=True)
# split_indices[1:] 提供了除第一个块之外的所有分界点
splitted_array = np.split(arr_sorted_by_col1, split_indices[1:])
print("\n按第二列分块后的数组(列表形式):")
for i, block in enumerate(splitted_array):
print(f"--- 块 {i} (第二列值为 {block[0, 1]}) ---\n", block)np.unique(arr_sorted_by_col1[:, 1], return_index=True)[1][1:] 能够找到第二列值发生变化的所有位置,这些位置作为 np.split 的参数,可以将排序后的数组精确地分割成多个子数组,每个子数组内部的第二列值都是相同的。
这个函数负责在每个分块(即第二列值已确定的子数组)内部,进一步根据第四列的值进行过滤,然后计算第一列的距离并找出N个最近邻的原始索引。
def query_trks(FULL_block, target_col4_value, N):
"""
在给定的数据块中,查找满足第四列条件且第一列最接近的N个行的原始索引。
参数:
FULL_block (np.ndarray): 一个NumPy数组,其中第二列的值是恒定的。
最后一列包含原始索引。
target_col4_value (float): 要匹配的第四列值。
N (int): 需要查找的最近邻行数。
返回:
np.ndarray: 一个数组,包含N个最近邻行的原始索引。
如果符合条件的行数不足N,则返回所有符合条件的行的索引。
"""
# 过滤出第四列值与目标值相等的行
# 注意:这里假设第四列是索引为4,但根据问题描述,它是索引3(0-based)
# 在示例数据中,我们假设是索引3
# 根据问题描述,是第四列(索引3)
filt_mask = (FULL_block[:, 3] == target_col4_value)
# 获取过滤后的行的索引(在FULL_block内部的相对索引)
internal_filt_indices = np.where(filt_mask)[0]
if len(internal_filt_indices) == 0:
return np.array([], dtype=int) # 没有匹配的行
# 提取过滤后的行的第一列值
trks_col0 = FULL_block[internal_filt_indices, 0]
# 使用广播机制计算所有过滤后的行之间第一列值的绝对差值
# trks_col0[:, None] 将一维数组转换为列向量,与 trks_col0 进行元素级减法
# 得到一个 (len(trks_col0), len(trks_col0)) 的差值矩阵
diff_matrix = np.abs(trks_col0[:, None] - trks_col0)
# 对差值矩阵按列排序,获取排序后的索引
# argsort(axis=0) 对每一列进行排序,返回排序后的索引
# [:N] 获取前N个最小差值的索引
# 注意:这里需要处理自身与自身的距离为0的情况,通常我们希望排除自身
# 一种方法是先将对角线元素设为无穷大,或者在获取N个索引后排除自身
# 考虑到实际需求,通常N个最近邻会包含自身(距离为0),如果需要排除,需额外处理。
# 这里的argsort会把0距离的自身排在第一位。
# 为了排除自身,我们可以将对角线元素设置为一个大值
np.fill_diagonal(diff_matrix, np.inf)
# 重新排序获取前N个最小差值的索引
# argsort(axis=0) 会对每一列进行排序,返回排序后的索引
# [:N] 获取前N个最小差值的索引
clo
sest_internal_indices = diff_matrix.argsort(axis=0)[:N]
# 将内部索引转换回 FULL_block 中的实际索引
# 然后再通过 FULL_block 找到其原始索引
# 最终结果需要针对每个原始行返回 N 个索引。
# 这里的 diff_matrix 是针对 trks_col0 的,所以 closest_internal_indices 也是 trks_col0 的索引。
# 我们需要的是 FULL_block 中对应行的原始索引。
# 创建一个空的列表来存储每个查询行的N个最近邻原始索引
result_indices = np.empty((len(internal_filt_indices), N), dtype=int)
for i, current_row_internal_idx in enumerate(internal_filt_indices):
# 对于当前行 (FULL_block[current_row_internal_idx]),
# 找到其在 trks_col0 中的位置 (j)
# diff_matrix 的第 j 列包含了当前行与其他行的距离
# 找到当前行在 trks_col0 内部的索引
j = np.where(internal_filt_indices == current_row_internal_idx)[0][0]
# 获取第 j 列中 N 个最近邻的内部索引
n_closest_in_trks_col0 = closest_internal_indices[:, j]
# 将这些内部索引映射回 FULL_block 的内部索引
n_closest_in_full_block = internal_filt_indices[n_closest_in_trks_col0]
# 提取这些行对应的原始索引(最后一列)
result_indices[i] = FULL_block[n_closest_in_full_block, -1].astype(int)
return result_indices
# 假设 N = 2
N = 2
# 创建一个列表来存储每个分块计算出的结果
all_computed_indices = []
# 遍历每个分块并调用 query_trks
for block in splitted_array:
# 在每个block中,第二列的值是相同的,我们只需获取其值
# 并且对于block中的每一行,我们都需要找到N个最近邻
# 假设我们为block中的每一行查找最近邻
# 我们需要迭代block中的每一行作为“当前行”来查询
# 获取 block 中所有行的原始索引,这些是需要填充结果的行
original_indices_in_block = block[:, -1].astype(int)
# 为当前 block 创建一个临时存储结果的数组
block_results = np.empty((len(block), N), dtype=int)
for i, row in enumerate(block):
# 当前行的第二列值和第四列值
current_col1_val = row[1]
current_col4_val = row[3]
current_col0_val = row[0]
# 过滤出与当前行第四列值相同的行
# 这里的 FULL_block 实际上就是当前的 block,因为我们已经在外部按 col1 分割了
# 并且 query_trks 应该只返回与 target_col4_value 匹配的行的最近邻
# 优化:query_trks 应该接收一个 block 和一个 target_col4_value
# 并且它应该为 block 中所有满足 target_col4_value 的行计算最近邻
# 重新设计 query_trks,使其能够处理一个 block 中的所有行
# 原始的 query_trks 假设 `trk` 是一个值,而不是整个列
# 让我们回到原始答案的逻辑,它通过 `a[:, 0]` 传入了整个第一列,
# 这意味着 `query_trks` 内部会为 `trks` 中的每个元素找到最近邻。
# 这里的 `trks` 是 `FULL[filt, 0]`,即过滤后的第一列。
# 让我们按照答案的逻辑重新构建 query_trks
# `query_trks(FULL, trk, v, N)`
# `FULL` 是当前的 `block`
# `trk` 在答案中被移除,因为 `trks = FULL[filt, 0]` 已经包含了所有需要比较的第一列值
# `v` 是 `target_col4_value`
相关文章:
潮流网站制作头像软件下载,适合母子的网名有哪些?
如何选择高效可靠的多用户建站源码资源?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
宿州网站制作公司兴策,安徽省低保查询网站?
开心动漫网站制作软件下载,十分开心动画为何停播?
如何设计高效校园网站?
如何快速上传建站程序避免常见错误?
网站制作企业,网站的banner和导航栏是指什么?
如何确认建站备案号应放置的具体位置?
已有域名如何快速搭建专属网站?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
学校建站服务器如何选型才能满足性能需求?
如何用wdcp快速搭建高效网站?
广州商城建站系统开发成本与周期如何控制?
油猴 教程,油猴搜脚本为什么会网页无法显示?
广东专业制作网站有哪些,广东省能源集团有限公司官网?
太原网站制作公司有哪些,网约车营运证查询官网?
如何撰写建站申请书?关键要点有哪些?
电商网站制作价格怎么算,网上拍卖流程以及规则?
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
我的世界制作壁纸网站下载,手机怎么换我的世界壁纸?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
网站制作需要会哪些技术,建立一个网站要花费多少?
整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?
开源网站制作软件,开源网站什么意思?
网站制作公司,橙子建站是合法的吗?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
如何通过商城免费建站系统源码自定义网站主题?
内网网站制作软件,内网的网站如何发布到外网?
C++如何使用std::optional?(处理可选值)
c# 在ASP.NET Core中管理和取消后台任务
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
香港服务器如何优化才能显著提升网站加载速度?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
微课制作网站有哪些,微课网怎么进?
微信推文制作网站有哪些,怎么做微信推文,急?
如何在Golang中指定模块版本_使用go.mod控制版本号
MySQL查询结果复制到新表的方法(更新、插入)
如何在Windows 2008云服务器安全搭建网站?
如何在万网自助建站中设置域名及备案?
c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
网站制作公司排行榜,四大门户网站排名?
网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?
c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】
如何快速查询域名建站关键信息?
家具网站制作软件,家具厂怎么跑业务?
香港服务器选型指南:免备案配置与高效建站方案解析
如何在IIS中新建站点并解决端口绑定冲突?
*请认真填写需求信息,我们会在24小时内与您取得联系。