如何从numpy.ndarray中移除z坐标≤0的粒子轨迹元素?
问题:筛选粒子轨迹数组中z坐标大于0的元素
原始粒子轨迹计算代码
import numpy as np # 原代码遗漏numpy导入,需补充 c = -299792458 q = -1 m = 0.002 v_x = 0 v_y = 0 v_z = c*0.994 x_i,y_i,z_i = 1,1,100 v_xi,v_yi,v_zi = 1,1,v_z h = 1e-12 timesteps = list(range(1,int(4e5))) x,y,z = x_i,y_i,z_i v_xi,v_yi,z_yi = v_xi,v_yi,v_zi height = 1 radius = 0.1 B_r = 12 Vol = 0.790524 B = lambda x,y,z : (B_r*Vol)/(4*np.pi*np.sqrt(x**2 + y**2 + z**2)) B_x = lambda x,y,z : B(x,y,z)*(3*z*x) B_y = lambda x,y,z : B(x,y,z)*(3*z*y) B_z = lambda x,y,z : B(x,y,z)*(2*z**2 - x**2 - y**2) def F_x(x,y,z,v_x,v_y,v_z): return((q/(m*c))*(v_y*B_z(x,y,z) - v_z*B_y(x,y,z))) def F_y(x,y,z,v_x,v_y,v_z): return((q/(m*c))*(v_z*B_x(x,y,z) - v_x*B_z(x,y,z))) def F_z(x,y,z,v_x,v_y,v_z): return((q/(m*c))*(v_x*B_y(x,y,z) - v_y*B_x(x,y,z))) p = np.zeros((len(timesteps)+1,3)) p[0,:] = [x_i,y_i,z_i] v = np.zeros((len(timesteps)+1,3)) v[0,:] = [v_xi,v_yi,v_zi] for i in range(len(timesteps)): p[i+1,:] = p[i,:] + h*v[i,:] v[i+1,0] = v[i,0] + h*F_x(*p[i,:],*v[i,:]) v[i+1,1] = v[i,1] + h*F_y(*p[i,:],*v[i,:]) v[i+1,2] = v[i,2] + h*F_z(*p[i,:],*v[i,:]) if p[i,2]<0: break
需求说明
生成的数组p形状为(400000, 3),需保留所有z坐标大于0的元素,移除z坐标小于0的元素及其后的所有[0,0,0]元素。
尝试的错误代码及报错
for i in p: if p[i,2]==0: np.delete(p,1,i)
报错:IndexError: arrays used as indices must be of integer (or boolean) type
错误原因分析
- 索引类型错误:
for i in p循环中,i是数组的每一行(如array([1.,1.,100.])),并非整数索引,用数组作为索引访问p[i,2]会触发类型错误。 np.delete参数顺序错误:np.delete的正确用法是np.delete(数组, 要删除的索引/索引列表, 轴),你颠倒了索引和轴的参数位置。- 低效操作方式:循环修改numpy数组效率极低,numpy的设计初衷是向量化操作,而非逐元素循环修改。
正确解决方案
方法一:找到第一个无效元素并截断(推荐,效率更高)
由于粒子向下运动,z坐标从100递减,一旦z<0就会触发循环break,后续元素全为[0,0,0],因此只需找到第一个z≤0的位置,截断数组即可:
import numpy as np # 找到所有z≤0的元素索引 invalid_positions = np.where(p[:, 2] <= 0)[0] if len(invalid_positions) > 0: # 取第一个无效位置之前的所有元素 p_filtered = p[:invalid_positions[0]] else: # 所有元素z都>0,直接复制原数组 p_filtered = p.copy()
方法二:布尔索引直接筛选
通过布尔数组直接提取所有z>0的元素,简单直观:
p_filtered = p[p[:, 2] > 0]
内容的提问来源于stack exchange,提问作者summersfreezing
相关产品推荐
相关产品推荐

