假设我在3个维度中有一个30个点的数组,在python中被转换为numpy数组:
import numpy as np
b = np.round(np.random.random((30,3))*20)
b = b - b.mean(axis=0)
我想把这些点分成8个象限,参考"质量中心"点云。我可以这样做:
for a in (b, -b):
q_list = a[a[:,0]>0.][a[a[:,0]>0.][:,1]>0][a[a[:,0]>0.][a[a[:,0]>0.][:,1]>0][:,2]>0]
quad_list.append(q_list * sign)
q_list = a[a[:,0]>0.][a[a[:,0]>0.][:,1]>0][a[a[:,0]>0.][a[a[:,0]>0.][:,1]>0][:,2]<=0]
quad_list.append(q_list * sign)
q_list = a[a[:,0]>0.][a[a[:,0]>0.][:,1]<=0][a[a[:,0]>0.][a[a[:,0]>0.][:,1]<=0][:,2]>0]
quad_list.append(q_list * sign)
q_list = a[a[:,0]>0.][a[a[:,0]>0.][:,1]<=0][a[a[:,0]>0.][a[a[:,0]>0.][:,1]<=0][:,2]<=0]
quad_list.append(q_list * sign)
sign *= -1
当然,这很好用。它返回一个包含八个位置坐标数组的列表,每个位置坐标只包含特定象限中的点。但是我觉得应该有更清晰,更简洁的方法来处理这个问题。建议?
答案 0 :(得分:3)
这是一个递归解决方案。它应该适用于任意数量的维度。
public static class ColorBar
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
public enum Color { None, Green, Red, Yellow }
public static void SetState(this ProgressBar pBar, Color newColor, int newValue)
{
if (pBar.Value == pBar.Minimum) // If it has not been painted yet, paint the whole thing using defualt color...
{ // Max move is instant and this keeps the initial move from going out slowly
pBar.Value = pBar.Maximum; // in wrong color on first painting
SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
}
pBar.Value = newValue;
SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero); // run it out to the correct spot in default
SendMessage(pBar.Handle, 1040, (IntPtr)(int)newColor, IntPtr.Zero); // now turn it the correct color
}
}
答案 1 :(得分:0)
对于大型数组,递归的计算量可能太大。
一个更好的选择可能是一个函数,它可以返回点本身分为四部分,或者只返回四分之一的索引而不递归(仍然应该适用于任意数量的维度)。
import numpy as np
def split_into_quadrants(points, get_quadrants_index=False):
ndims = points.shape[1]
existing_quadrants = list(itertools.product([-1, 1], repeat=ndims))
quadrants_dict = dict(zip(existing_quadrants,range(len(existing_quadrants))))
sign_points = np.sign(points)
quadrants_idx = np.apply_along_axis(lambda x: quadrants_dict[(tuple(x.astype(int)))], 1, sign_points)
if get_quadrants_index:
return quadrants_idx
points_split_into_quadrants = []
for i in set(quadrants_idx):
points_split_into_quadrants.append(points[quadrants_idx==i])
return points_split_into_quadrants
b = np.round(np.random.random((30,3))*20)
b = b - b.mean(axis=0)
print(split_into_quadrants(b,get_quadrants_index=False))