我有一个二维数组,表示极坐标系中各个位置的函数值。例如:
import numpy as np
radius = np.linspace(0, 1, 50)
angle = np.linspace(0, 2*np.pi, radius.size)
r_grid, a_grid = np.meshgrid(radius, angle)
data = np.sqrt((r_grid/radius.max())**2
+ (a_grid/angle.max())**2)
此处data
排列在一个与极坐标相对应的矩形网格中。我想重新排列数组中的数据,以使轴代表相应的笛卡尔坐标系。新旧布局可以如下显示:
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=plt.figaspect(0.5))
ax1.set(title='Polar coordinates', xlabel='Radius', ylabel='Angle')
ax1.pcolormesh(r_grid, a_grid, data)
ax2.set(title='Cartesian coordinates', xlabel='X', ylabel='Y')
x_grid = r_grid * np.cos(a_grid)
y_grid = r_grid * np.sin(a_grid)
ax2.pcolormesh(x_grid, y_grid, data)
这里明确给出了坐标,并相应地调整了图。我希望将数据重新排列在数据数组本身中。它应该包含所有值,可以选择填充零以适合形状(类似于scipy.ndimage.rotate(..., reshape=True)
)。
如果我手动遍历极坐标数组以计算笛卡尔坐标,则结果包含理想情况下也应填充的空白区域:
scipy.ndimage.rotate(..., reshape=True)
new = np.zeros_like(data)
visits = np.zeros_like(new)
for r, a, d in np.nditer((r_grid, a_grid, data)):
i = 0.5 * (1 + r * np.sin(a)) * new.shape[0]
j = 0.5 * (1 + r * np.cos(a)) * new.shape[1]
i = min(int(i), new.shape[0] - 1)
j = min(int(j), new.shape[1] - 1)
new[i, j] += d
visits[i, j] += 1
new /= np.maximum(visits, 1)
ax2.imshow(new, origin='lower')
是否有一种方法来实现转换,同时避免在结果数据数组中出现空白区域?
您可以遍历笛卡尔数组,将每个网格点转换为极坐标,并通过从极坐标数据中进行插值来逼近函数值。但是,由于缺少足够接近的数据,您可能仍然希望将角落区域留空。
我认为没有更好的方法,除非您当然可以使用原始功能。
tl; dr:不,并非不更改您的问题的某些条件。
您看到的文物是转换的属性。这不是由于所有半径的角度分辨率都是固定的。因此,这不是由于转换的错误或错误实现造成的。笛卡尔网格仅表示在这些区域具有更高的特殊分辨率,因为极坐标图中有解析点。
处理该问题的唯一“干净”方法(我现在可以想到)是在极坐标中具有可调分辨率,以解决1 / r缩放问题。 (如果您输入数据允许的话)
一种在没有间隙的情况下可视化它的作弊方式,是将它们随机分布在间隙上。这里的论据是,您没有解决方案来决定他们从哪个bin开始。因此,您可以将它们随机地放入一个可能是起源的容器中,而不是将它们全部放入一个容器中(就像您现在所做的那样)。但是,我谨此劝阻。它只是给您一个漂亮的情节。请注意,这在某种程度上等同于您问题中右上图的行为。
这并没有真正给出预期的结果,但是可能会在某些需要的更正之后帮助您实现解决方案...
def polar_to_cartesian(data):
new = np.zeros_like(data)
x = np.linspace(-1, 1, new.shape[1])
y = np.linspace(-1, 1, new.shape[0])
for i in range(new.shape[0]):
for j in range(new.shape[1]):
x0, y0 = x[j], y[i]
r, a = np.sqrt(x0**2 + y0**2), np.arctan(y0 / x0)
data_i = np.argmin(np.abs(a_grid[:, 0] - a))
data_j = np.argmin(np.abs(r_grid[0, :] - r))
val = data[data_i, data_j]
new[i, j] = val
return new
new = polar_to_cartesian(data)
fig, ax = plt.subplots()
ax.imshow(new, origin='lower')