在 numpy 数组上替换 double for 循环(通过索引到其他数组)
Replace double for loop (with indexing into other arrays) over numpy array
这是我正在处理的示例:
processed_data = np.empty_like(data)
min_per_col = np.amin(data, axis=0) # axis0 for col, axis1 for row
max_per_col = np.amax(data, axis=0) # axis0 for col, axis1 for row
for row_idx, row in enumerate(data):
for col_idx, val in enumerate(row):
processed_data[row_idx][col_idx] = (val - min_per_col[col_idx]) / (max_per_col[col_idx] - min_per_col[col_idx])
data
被定义为二维 numpy 数组。我实际上是在尝试使用 min_per_col
和 max_per_col
.
中的相关值对 data
中的每个元素执行一些操作
我似乎无法弄清楚要采取的方法。从 看来,答案似乎是重塑数组,以便广播正常工作。
直觉上,我认为广播的工作方式是:
# Results of min_per_col:
# [min1 min2 min3 min4 min5]
# Transformation to (call this 2d_min_per_col):
# [[min1 min2 min3 min4 min5],
# [min1 min2 min3 min4 min5],
# [min1 min2 min3 min4 min5]
# ...
# [min1 min2 min3 min4 min5]]
# which basically duplicates min_per_col into a 2d array form.
# Do the same for max (2d_max_per_col)
# processed_data = (data - 2d_min_per_col) / (2d_max_per_col - 2d_min_per_col)
这种方法有意义吗?或者对于如何处理这样的事情还有其他答案吗?
请让我知道是否有任何其他内容对本文有帮助 post!谢谢。
编辑: 感谢疯狂物理学家的帮助!尝试之后:
processed_data = np.empty_like(data)
min_per_col = np.amin(data, axis=0) # axis0 for col, axis1 for row
max_per_col = np.amax(data, axis=0) # axis0 for col, axis1 for row
for row_idx, row in enumerate(data):
for col_idx, val in enumerate(row):
processed_data[row_idx, col_idx] = (val - min_per_col[col_idx]) / (max_per_col[col_idx] - min_per_col[col_idx])
print("version 1\n", processed_data)
processed_data = (data - min_per_col) / (max_per_col - min_per_col)
print("version 2\n", processed_data)
return processed_data
它的工作原理相同,而且速度更快!
version 1
[[0.25333333 0.13793103 0.14285714]
[0.32 0.79310345 0.92857143]
[0.13333333 0.48275862 0.51785714]
...
[0.28 0.4137931 0.125 ]
[0.01333333 0.24137931 0.75 ]
[0.08 0.20689655 0.23214286]]
version 2
[[0.25333333 0.13793103 0.14285714]
[0.32 0.79310345 0.92857143]
[0.13333333 0.48275862 0.51785714]
...
[0.28 0.4137931 0.125 ]
[0.01333333 0.24137931 0.75 ]
[0.08 0.20689655 0.23214286]]
感谢您的快速帮助:D
你明白了它的要点,但广播的全部意义在于你不需要扩展数组来对它们进行操作:形状在右边排列。因此,例如,假设 data.shape
是 (M, N)
您的数组形状在数学运算中看起来像这样:
data: (M, N)
processed_data: (M, N)
min_per_col: (N,)
max_per_col: (N,)
请注意,min_per_col
和 max_per_col
完全对齐。这意味着您的整个循环变得简单
processed_data = (data - min_per_col) / (max_per_col - min_per_col)
# (M, N) (N,)
# (M, N)
每个运算符下的注释显示广播输出的形状。
顺便说一句,您可以使用 np.ptp
:
一步计算分母
processed_data = (data - np.min(data, axis=0)) / np.ptp(data, axis=0)
这是我正在处理的示例:
processed_data = np.empty_like(data)
min_per_col = np.amin(data, axis=0) # axis0 for col, axis1 for row
max_per_col = np.amax(data, axis=0) # axis0 for col, axis1 for row
for row_idx, row in enumerate(data):
for col_idx, val in enumerate(row):
processed_data[row_idx][col_idx] = (val - min_per_col[col_idx]) / (max_per_col[col_idx] - min_per_col[col_idx])
data
被定义为二维 numpy 数组。我实际上是在尝试使用 min_per_col
和 max_per_col
.
data
中的每个元素执行一些操作
我似乎无法弄清楚要采取的方法。从
直觉上,我认为广播的工作方式是:
# Results of min_per_col:
# [min1 min2 min3 min4 min5]
# Transformation to (call this 2d_min_per_col):
# [[min1 min2 min3 min4 min5],
# [min1 min2 min3 min4 min5],
# [min1 min2 min3 min4 min5]
# ...
# [min1 min2 min3 min4 min5]]
# which basically duplicates min_per_col into a 2d array form.
# Do the same for max (2d_max_per_col)
# processed_data = (data - 2d_min_per_col) / (2d_max_per_col - 2d_min_per_col)
这种方法有意义吗?或者对于如何处理这样的事情还有其他答案吗?
请让我知道是否有任何其他内容对本文有帮助 post!谢谢。
编辑: 感谢疯狂物理学家的帮助!尝试之后:
processed_data = np.empty_like(data)
min_per_col = np.amin(data, axis=0) # axis0 for col, axis1 for row
max_per_col = np.amax(data, axis=0) # axis0 for col, axis1 for row
for row_idx, row in enumerate(data):
for col_idx, val in enumerate(row):
processed_data[row_idx, col_idx] = (val - min_per_col[col_idx]) / (max_per_col[col_idx] - min_per_col[col_idx])
print("version 1\n", processed_data)
processed_data = (data - min_per_col) / (max_per_col - min_per_col)
print("version 2\n", processed_data)
return processed_data
它的工作原理相同,而且速度更快!
version 1
[[0.25333333 0.13793103 0.14285714]
[0.32 0.79310345 0.92857143]
[0.13333333 0.48275862 0.51785714]
...
[0.28 0.4137931 0.125 ]
[0.01333333 0.24137931 0.75 ]
[0.08 0.20689655 0.23214286]]
version 2
[[0.25333333 0.13793103 0.14285714]
[0.32 0.79310345 0.92857143]
[0.13333333 0.48275862 0.51785714]
...
[0.28 0.4137931 0.125 ]
[0.01333333 0.24137931 0.75 ]
[0.08 0.20689655 0.23214286]]
感谢您的快速帮助:D
你明白了它的要点,但广播的全部意义在于你不需要扩展数组来对它们进行操作:形状在右边排列。因此,例如,假设 data.shape
是 (M, N)
您的数组形状在数学运算中看起来像这样:
data: (M, N)
processed_data: (M, N)
min_per_col: (N,)
max_per_col: (N,)
请注意,min_per_col
和 max_per_col
完全对齐。这意味着您的整个循环变得简单
processed_data = (data - min_per_col) / (max_per_col - min_per_col)
# (M, N) (N,)
# (M, N)
每个运算符下的注释显示广播输出的形状。
顺便说一句,您可以使用 np.ptp
:
processed_data = (data - np.min(data, axis=0)) / np.ptp(data, axis=0)