从 ND 到 1D 阵列
- 2025-02-27 09:06:00
- admin 原创
- 75
问题描述:
假设我有一个数组a
:
a = np.array([[1,2,3], [4,5,6]])
array([[1, 2, 3],
[4, 5, 6]])
我想将其转换为一维数组(即列向量):
b = np.reshape(a, (1,np.product(a.shape)))
但这又回来了
array([[1, 2, 3, 4, 5, 6]])
这与以下内容不同:
array([1, 2, 3, 4, 5, 6])
我可以取该数组的第一个元素,手动将其转换为一维数组:
b = np.reshape(a, (1,np.product(a.shape)))[0]
但这要求我知道原始数组有多少维(并且在处理更高维度时连接 [0])
是否存在一种与维度无关的方法可以从任意 ndarray 中获取列/行向量?
解决方案 1:
使用np.ravel(用于 1D 视图)或np.ndarray.flatten(用于 1D 副本)或np.ndarray.flat(用于 1D 迭代器):
In [12]: a = np.array([[1,2,3], [4,5,6]])
In [13]: b = a.ravel()
In [14]: b
Out[14]: array([1, 2, 3, 4, 5, 6])
请注意,如果可能,将ravel()
返回。因此,修改也会修改。如果 1D 元素在内存中连续,则返回,但如果例如使用非单位步长(例如)对另一个数组进行切片,则将返回 。view
`ab
aravel()
viewcopy
a`a = x[::2]
如果您想要的是副本而不是视图,请使用
In [15]: c = a.flatten()
如果您只想要一个迭代器,请使用np.ndarray.flat
:
In [20]: d = a.flat
In [21]: d
Out[21]: <numpy.flatiter object at 0x8ec2068>
In [22]: list(d)
Out[22]: [1, 2, 3, 4, 5, 6]
解决方案 2:
In [14]: b = np.reshape(a, (np.product(a.shape),))
In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])
或者,简单地说:
In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])
解决方案 3:
我想看看包括unutbu在内的答案中提到的函数的基准测试结果。
还要指出的是,numpy doc建议在 case view 的情况下使用arr.reshape(-1)
。(即使ravel
在以下结果中速度稍快一些)
TL;DR:
np.ravel
性能最强(但差距很小)。
基准
功能:
np.ravel
:如果可能的话,返回视图np.reshape(-1)
:如果可能的话,返回视图np.flatten
:返回副本np.flat
:返回numpy.flatiter
。类似于iterable
numpy 版本:'1.18.0'
ndarray
不同尺寸的执行时间
+-------------+----------+-----------+-----------+-------------+
| function | 10x10 | 100x100 | 1000x1000 | 10000x10000 |
+-------------+----------+-----------+-----------+-------------+
| ravel | 0.002073 | 0.002123 | 0.002153 | 0.002077 |
| reshape(-1) | 0.002612 | 0.002635 | 0.002674 | 0.002701 |
| flatten | 0.000810 | 0.007467 | 0.587538 | 107.321913 |
| flat | 0.000337 | 0.000255 | 0.000227 | 0.000216 |
+-------------+----------+-----------+-----------+-------------+
结论
ravel
并且reshape(-1)
的执行时间是一致的,并且与 ndarray 大小无关。但是,ravel
速度稍快,但reshape
在重塑大小方面提供了灵活性。(也许这就是为什么numpy doc建议使用它的原因。或者在某些情况下reshape
返回 view 而不ravel
返回)。如果您正在处理大尺寸的 ndarray,使用
flatten
可能会导致性能问题。建议不要使用它。除非您需要数据的副本来做其他事情。
使用的代码
import timeit
setup = '''
import numpy as np
nd = np.random.randint(10, size=(10, 10))
'''
timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
timeit.timeit('nd.flat', setup=setup, number=1000)
解决方案 4:
对于具有不同大小的数组列表,请使用以下命令:
import numpy as np
# ND array list with different size
a = [[1],[2,3,4,5],[6,7,8]]
# stack them
b = np.hstack(a)
print(b)
输出:
[1 2 3 4 5 6 7 8]
解决方案 5:
最简单的方法之一是使用flatten()
,如以下示例:
import numpy as np
batch_y =train_output.iloc[sample, :]
batch_y = np.array(batch_y).flatten()
我的阵列是这样的:
0
0 6
1 6
2 5
3 4
4 3
.
.
.
使用后flatten()
:
array([6, 6, 5, ..., 5, 3, 6])
这也是此类错误的解决方案:
Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)'
解决方案 6:
虽然这没有使用 np 数组格式,(懒得修改我的代码)但这应该可以满足您的要求...如果您确实想要一个列向量,您将需要转置向量结果。这完全取决于您打算如何使用它。
def getVector(data_array,col):
vector = []
imax = len(data_array)
for i in range(imax):
vector.append(data_array[i][col])
return ( vector )
a = ([1,2,3], [4,5,6])
b = getVector(a,1)
print(b)
Out>[2,5]
因此,如果您需要转置,您可以执行以下操作:
def transposeArray(data_array):
# need to test if this is a 1D array
# can't do a len(data_array[0]) if it's 1D
two_d = True
if isinstance(data_array[0], list):
dimx = len(data_array[0])
else:
dimx = 1
two_d = False
dimy = len(data_array)
# init output transposed array
data_array_t = [[0 for row in range(dimx)] for col in range(dimy)]
# fill output transposed array
for i in range(dimx):
for j in range(dimy):
if two_d:
data_array_t[j][i] = data_array[i][j]
else:
data_array_t[j][i] = data_array[j]
return data_array_t
解决方案 7:
所有建议的解决方案中最好且最快的是:np.reshape()
%timeit img1ary = np.reshape(img2ary,(np.product(img2ary.shape),1))
9.3 µs ± 69.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit img1ary = img2ary.ravel()
157 ns ± 1.32 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit img1ary = img2ary.flatten()
961 ns ± 5.77 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
扫码咨询,免费领取项目管理大礼包!