如果您希望使用 list
而不是 tuple
,可以使用以下技巧:
- 使用
.tolist()
将数组转换为 list
的list
- 确保更改其中一个最内层的
list
的大小(misalign)
- 将
list
的list
再次转换为 NumPy 数组
- 修复第2点修改。
该函数在以下函数中实现:last_dim_as_list()
:
import numpy as np
def last_dim_as_list(arr):
if arr.ndim > 1:
arr_list = arr.tolist()
temp = arr_list
for _ in range(arr.ndim - 1):
temp = temp[0]
temp.append(None)
result = np.array(arr_list)
temp.pop()
else:
result = np.empty(1, dtype=object)
result[0] = arr.tolist()
return result
np.random.seed(0)
in_arr = np.random.randint(0, 9, (2, 3, 2))
out_arr = last_dim_as_list(in_arr)
print(in_arr)
print(in_arr.shape)
print(in_arr.dtype)
print(out_arr)
print(out_arr.shape)
print(out_arr.dtype)
然而,我不建议采用这种方法,除非你真的知道自己在做什么。
大多数情况下,最好将所有内容保留为更高维度的NumPy数组,并充分利用NumPy索引。
请注意,这也可以使用明确的循环来完成,但是所提出的方法对于足够大的输入应该会更快:
def last_dim_as_list_loop(arr):
shape = arr.shape
result = np.empty(arr.shape[:-1], dtype=object).ravel()
for k in range(arr.shape[-1]):
for i in range(result.size):
if k == 0:
result[i] = []
result[i].append(arr[..., k].ravel()[i])
return result.reshape(shape[:-1])
out_arr2 = last_dim_as_list_loop(in_arr)
print(out_arr2)
print(out_arr2.shape)
print(out_arr2.dtype)
但是这个最后的时间并不是特别惊人:
%timeit last_dim_as_list(in_arr)
%timeit last_dim_as_list_loop(in_arr)
@PaulPanzer 提出的基于 view
的方法 proposed 非常优雅,比 last_dim_as_list()
中提出的技巧更高效,因为它只需要循环(内部)一次数组,而不是两次:
def last_dim_as_tuple(arr):
dtype = [(str(i), arr.dtype) for i in range(arr.shape[-1])]
return arr.view(dtype)[..., 0].astype(object)
因此,在足够大的输入上,时间更有利:
in_arr = np.random.random((6602, 3176, 2))
%timeit last_dim_as_list(in_arr)
%timeit last_dim_as_tuple(in_arr)
axis
参数的方法可能是更好的选择。 - norok2