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

Scipy cKDTree query_ball_point如何设置查询最小半径?

Great question—this is a common optimization when working with expanding radius queries using k-d trees. Unfortunately, scipy.spatial.cKDTree.query_ball_point doesn’t have a built-in parameter to specify a minimum radius, but we can achieve exactly what you want efficiently by leveraging set operations (or numpy array differences) to isolate points that fall between your previous radius and the current expanded radius.

Here’s why your current approach is inefficient: each call to query_ball_point(origin, i) recalculates distances for all points up to radius i, including those you already found in smaller radii. Instead, we can compute the incremental points added at each step and build our cumulative results from there, avoiding redundant processing of already-included points.

Modified Code Example

Let’s adjust your loop to track both the cumulative set of points and the incremental points added at each radius step. This way, you only process new points each iteration, and you can save either the cumulative results (all points up to the current radius) or just the incremental ones (points between the previous and current radius):

import pandas as pd
from scipy.spatial import cKDTree

# Assume these are defined: kdt, origin, lmax, sphererads, DF (a dictionary to store results)
cumulative_gals = set()
n = 0
prev_radius = 0

# Start from the first non-zero radius (since radius 0 will only include the origin if present)
for current_radius in range(sphererads, lmax + sphererads, sphererads):
    # Get all points within the current expanded radius
    all_gals = kdt.query_ball_point(origin, current_radius)
    all_gals_set = set(all_gals)
    
    # Isolate points that are new (between prev_radius and current_radius)
    incremental_gals = all_gals_set - cumulative_gals
    
    # Update our cumulative set with the new points
    cumulative_gals.update(incremental_gals)
    
    # Save the cumulative results (all points up to current_radius) to your DataFrame dict
    DF[n] = pd.DataFrame(list(cumulative_gals))
    
    # If you only want to save the incremental points (the new ones added this step), use this instead:
    # DF[n] = pd.DataFrame(list(incremental_gals))
    
    n += 1
    prev_radius = current_radius

For Large Datasets: Numpy Alternative

If you’re working with very large datasets, using numpy arrays instead of sets can be more efficient in terms of memory and speed:

import numpy as np
import pandas as pd
from scipy.spatial import cKDTree

cumulative_gals = np.array([], dtype=int)
n = 0
prev_radius = 0

for current_radius in range(sphererads, lmax + sphererads, sphererads):
    all_gals = np.array(kdt.query_ball_point(origin, current_radius), dtype=int)
    
    # Find points not already in the cumulative set
    incremental_gals = np.setdiff1d(all_gals, cumulative_gals, assume_unique=True)
    
    # Update cumulative array
    cumulative_gals = np.union1d(cumulative_gals, incremental_gals)
    
    # Save cumulative results
    DF[n] = pd.DataFrame(cumulative_gals)
    n += 1
    prev_radius = current_radius

Key Notes

  • The core idea here is that we’re using the difference between two radius queries to get only the points in the annulus between prev_radius and current_radius. This avoids reprocessing points you’ve already included in smaller radii.
  • While the query_ball_point call still computes all distances up to current_radius, this is unavoidable with cKDTree’s current API. However, using set/array differences saves you from redundant work when building your final results.
  • If you don’t need the cumulative set and only care about points in each annulus, you can skip updating the cumulative set and just save incremental_gals directly.

内容的提问来源于stack exchange,提问作者Chris Böttner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:56:21