连接不同大小的数组
Concatenating arrays of different sizes
我正在尝试对由 sklearn
中的 make_blobs
函数创建的 numpy 点数组执行四叉树算法。我正在尝试创建一个递归分区 KMeans,其中质心位于 space 的每个四叉树分区中。这是我的分区函数:
def partition(self, data):
if data.size != 0:
minX = np.min(data[:,0])
maxX = np.max(data[:,0])
minY = np.min(data[:,1])
maxY = np.max(data[:,1])
middleX = (maxX + minX)/2
middleY = (maxY + minY)/2
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
parts2 = np.array([i for i in data if i[0] > middleX and i[1] > middleY])
parts3 = np.array([i for i in data if i[0] < middleX and i[1] < middleY])
parts4 = np.array([i for i in data if i[0] > middleX and i[1] < middleY])
parts = np.array([parts1, parts2, parts3, parts4])
return parts
else:
return np.array([[], [], [], []])
我的 make_blobs
函数创建的数据集具有以下结构:
[[ 9.26360832 -9.18849755] [ 7.3971609 9.92622627] [
7.29022892 -10.39359926] ... [ 8.66667995 -11.99184453] [ 5.80627027 10.53947197] [ 6.14214488 -0.73405016]]
此函数的示例输出可能是:
[array([[3.95348068, 4.74190848]]) array([[4.47174131, 4.67345222],
[4.73856072, 4.68464296]]) array([], dtype=float64) array([[4.48952751, 4.38898038],
[4.47734611, 4.34300488]])]
,也就是形状(4,)。然而,它也可以是形状 (4,1,2),如下所示:
[[[-7.17718091 -4.92636967]]
[[-6.66796907 -4.94025585]]
[[-7.03501112 -5.17783394]]
[[-6.45835039 -5.17271443]]]
然后我尝试连接分区,以便得到一个包含分区的大数组。这是负责串联的行:
part_data = np.hstack([self.partition(d) for d in part_data if np.shape(self.partition(d)) != (4,0)])
当分区为空或相等时出现问题,因此形状为(4,0)、(4,1,2) 或(4,2,2)。数组不能以这种方式连接。错误状态如下:
ValueError: all the input arrays must have same number of dimensions,
but the array at index 0 has 1 dimension(s) and the array at index 10
has 3 dimension(s)
是否可以忽略这些形状或以某种方式将它们重塑为 (4,)?也许有一些技巧可以不作为数组而是作为对象附加?如有任何回应,我将不胜感激。
这是此示例的完整代码:
import numpy as np
from sklearn.datasets import make_blobs
def generateDataset(k, dimensions, n_samples):
X, y_true = make_blobs(n_samples = n_samples, centers = k, n_features= dimensions, cluster_std = 1.1)
return X, y_true
X, y_true = generateDataset(3,2,10000)
def partition(data):
if data.size != 0:
minX = np.min(data[:,0])
maxX = np.max(data[:,0])
minY = np.min(data[:,1])
maxY = np.max(data[:,1])
middleX = (maxX + minX)/2
middleY = (maxY + minY)/2
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
parts2 = np.array([i for i in data if i[0] > middleX and i[1] > middleY])
parts3 = np.array([i for i in data if i[0] < middleX and i[1] < middleY])
parts4 = np.array([i for i in data if i[0] > middleX and i[1] < middleY])
parts = np.array([parts1, parts2, parts3, parts4])
return parts
else:
return np.array([[], [], [], []])
part_data = partition(X)
for i in range(6):
if i >= 1:
part_data = np.hstack([partition(d) for d in part_data if np.shape(partition(d)) != (4,0)])
当我第一次读到这个问题时,我以为你在尝试 hstack
形状为 (4,0), (4,1,2) or (4,2,2)
的数组。但是根据评论,似乎也有形状 (4,) 数组。
4
部分来自连接4个元素
parts = np.array([parts1, parts2, parts3, parts4])
每一个都是表达式的结果:
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
您没有提供 data
的示例(不要指望我们从您的代码中重新创建它!),甚至没有 parts
.[=45= 的示例]
当我构造一个示例二维数组时,猜测什么会起作用:
In [18]: data = np.array([[1,3],[2,4],[3,1]])
In [19]: [i for i in data] # iterate on the rows
Out[19]: [array([1, 3]), array([2, 4]), array([3, 1])]
各种'range'测试:
In [20]: [i for i in data if i[0]<2 and i[1]>2]
Out[20]: [array([1, 3])]
In [21]: np.array(_)
Out[21]: array([[1, 3]])
In [22]: _.shape
Out[22]: (1, 2)
In [23]: [i for i in data if i[0]<2 and i[1]>3]
Out[23]: []
In [24]: [i for i in data if i[0]<2 and i[1]>1]
Out[24]: [array([1, 3])]
In [25]: [i for i in data if i[0]<1 and i[1]>1]
Out[25]: []
In [26]: [i for i in data if i[0]<3 and i[1]>1]
Out[26]: [array([1, 3]), array([2, 4])]
In [27]: np.array([i for i in data if i[0]<3 and i[1]>1])
Out[27]:
array([[1, 3],
[2, 4]])
In [29]: np.array([i for i in data if i[0]<3 and i[1]>3])
Out[29]: array([[2, 4]])
所以我可以获得一个 parts
数组,它是 (0,)、(1,2) 或 (2,2)(或更多的第一维)。
将其中的 4 个加入一个数组并得到一个 (4,1,2) 等。但是等等,这 4 个测试中的每一个都可以给出不同大小的数组,在这种情况下 np.array(parts....)
将产生一个 object
形状为 (4,) 的 dtype 数组。
这是怎么回事?您混合了大部分 (4,) 对象 dtype 数组以及一些 (4,0) 和 (4,n,2) 形状的数字 dtype 数组?
除了完整的代码或最小的示例,我们还应该要求您显示您正在尝试的列表 hstack
:
[partition(d) for d in part_data if np.shape(partition(d)) != (4,0)]
让我们尝试从这些示例结果中的 4 个创建 partition
数组:
In [46]: [Out[20],Out[27],Out[25],Out[29]]
Out[46]:
[[array([1, 3])],
array([[1, 3],
[2, 4]]),
[],
array([[2, 4]])]
In [47]: x1=np.array([Out[20],Out[27],Out[25],Out[29]])
<ipython-input-47-b04a5e3fb51c>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
x1=np.array([Out[20],Out[27],Out[25],Out[29]])
In [48]: x1
Out[48]:
array([list([array([1, 3])]), array([[1, 3],
[2, 4]]), list([]), array([[2, 4]])],
dtype=object)
你收到 ragged array
警告了吗?请注意,结果数组是 (4,) object dtype.
如果所有部分都是相同的形状,例如 (1,2):
In [49]: x2=np.array([Out[29],Out[29],Out[29],Out[29]])
In [50]: x2.shape
Out[50]: (4, 1, 2)
In [51]: x2
Out[51]:
array([[[2, 4]],
[[2, 4]],
[[2, 4]],
[[2, 4]]])
或 (4,0)
In [54]: x3=np.array([Out[23],Out[23],Out[23],Out[23]])
In [55]: x3
Out[55]: array([], shape=(4, 0), dtype=float64)
In [56]: x4=np.array([Out[27],Out[27],Out[27],Out[27]])
In [57]: x4.shape
Out[57]: (4, 2, 2)
即使没有 (4,0) 我们也会得到尺寸不匹配:
In [59]: np.hstack((x1,x2,x4))
Traceback (most recent call last):
Input In [59] in <cell line: 1>
np.hstack((x1,x2,x4))
File <__array_function__ internals>:180 in hstack
File /usr/local/lib/python3.8/dist-packages/numpy/core/shape_base.py:343 in hstack
return _nx.concatenate(arrs, 0)
File <__array_function__ internals>:180 in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 1 has 3 dimension(s)
我们可以将 (4,) 中的几个连接成一个新的对象 dtype 数组:
In [61]: np.hstack((x1,x1,x1)).shape
Out[61]: (12,)
关键问题是 np.array((part1,part2,...))
不是制作 (4,) 对象 dtype 数组的可靠方法。有时如果生成 (4,) 并带有警告,有时它会生成 (4,0) 或 (4,n,2)。掩饰 ragged warning
你把你自己和我们都搞糊涂了!
如果我们定义一个辅助函数,我们就可以可靠地创建一个对象 dtype 数组,即使输入的形状完全相同:
In [62]: def foo(*args):
...: res = np.empty(len(args),object)
...: res[:] = args
...: return res
...:
用它重新创建 4 个部分:
In [63]: x1 = foo([Out[29],Out[29],Out[29],Out[29]])
In [64]: x1.shape,x1.dtype
Out[64]: ((1,), dtype('O'))
In [65]: x1 = foo(Out[29],Out[29],Out[29],Out[29])
In [66]: x1.shape, x1.dtype
Out[66]: ((4,), dtype('O'))
In [67]: x2=foo(Out[29],Out[29],Out[29],Out[29])
In [68]: x2.shape, x2.dtype
Out[68]: ((4,), dtype('O'))
In [69]: x3=foo(Out[23],Out[23],Out[23],Out[23])
In [70]: x3.shape, x3.dtype
Out[70]: ((4,), dtype('O'))
In [71]: x4=foo(Out[27],Out[27],Out[27],Out[27])
In [72]: x4.shape, x4.dtype
Out[72]: ((4,), dtype('O'))
In [73]: arr = np.hstack((x1,x2,x3,x4))
In [74]: arr.shape
Out[74]: (16,)
生成的数组有点乱,但值得一看。这真的是您想要的并且能够使用的吗:
In [75]: arr
Out[75]:
array([array([[2, 4]]), array([[2, 4]]), array([[2, 4]]), array([[2, 4]]),
array([[2, 4]]), array([[2, 4]]), array([[2, 4]]), array([[2, 4]]),
list([]), list([]), list([]), list([]), array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]), array([[1, 3],
[2, 4]]), array([[1, 3],
[2, 4]])], dtype=object)
等效列表可能同样有用:
In [76]: arr.tolist()
Out[76]:
[array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
[],
[],
[],
[],
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]])]
输入全部为空列表的 x3
情况可能需要一些改进:
In [80]: x3
Out[80]: array([list([]), list([]), list([]), list([])], dtype=object)
编辑
您添加的示例数组是:
[array([[3.95348068, 4.74190848]])
array([[4.47174131, 4.67345222],
[4.73856072, 4.68464296]])
array([], dtype=float64)
array([[4.48952751, 4.38898038],
[4.47734611, 4.34300488]])]
即(4,)(不是(4,0)或(4,1)),和object
dtype。这很像一个列表,包含对 4 个数组的引用。这些阵列的形状不同,(1,2),(2,2),(0,),(2,2)
。由于不同的形状,它只能制作一个对象 dtype 数组(带有参差不齐的数组警告)。
下面的示例是 (4,1,2),通过将 np.array
应用于 4 个形状均为 (1,2) 的数组的列表而制成。 np.array
优先制作多维数值数组。从该列表创建一个 (4,) 对象数组需要特殊操作,如我在 foo
函数中所示。
我正在尝试对由 sklearn
中的 make_blobs
函数创建的 numpy 点数组执行四叉树算法。我正在尝试创建一个递归分区 KMeans,其中质心位于 space 的每个四叉树分区中。这是我的分区函数:
def partition(self, data):
if data.size != 0:
minX = np.min(data[:,0])
maxX = np.max(data[:,0])
minY = np.min(data[:,1])
maxY = np.max(data[:,1])
middleX = (maxX + minX)/2
middleY = (maxY + minY)/2
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
parts2 = np.array([i for i in data if i[0] > middleX and i[1] > middleY])
parts3 = np.array([i for i in data if i[0] < middleX and i[1] < middleY])
parts4 = np.array([i for i in data if i[0] > middleX and i[1] < middleY])
parts = np.array([parts1, parts2, parts3, parts4])
return parts
else:
return np.array([[], [], [], []])
我的 make_blobs
函数创建的数据集具有以下结构:
[[ 9.26360832 -9.18849755] [ 7.3971609 9.92622627] [ 7.29022892 -10.39359926] ... [ 8.66667995 -11.99184453] [ 5.80627027 10.53947197] [ 6.14214488 -0.73405016]]
此函数的示例输出可能是:
[array([[3.95348068, 4.74190848]]) array([[4.47174131, 4.67345222], [4.73856072, 4.68464296]]) array([], dtype=float64) array([[4.48952751, 4.38898038], [4.47734611, 4.34300488]])]
,也就是形状(4,)。然而,它也可以是形状 (4,1,2),如下所示:
[[[-7.17718091 -4.92636967]]
[[-6.66796907 -4.94025585]]
[[-7.03501112 -5.17783394]]
[[-6.45835039 -5.17271443]]]
然后我尝试连接分区,以便得到一个包含分区的大数组。这是负责串联的行:
part_data = np.hstack([self.partition(d) for d in part_data if np.shape(self.partition(d)) != (4,0)])
当分区为空或相等时出现问题,因此形状为(4,0)、(4,1,2) 或(4,2,2)。数组不能以这种方式连接。错误状态如下:
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 10 has 3 dimension(s)
是否可以忽略这些形状或以某种方式将它们重塑为 (4,)?也许有一些技巧可以不作为数组而是作为对象附加?如有任何回应,我将不胜感激。 这是此示例的完整代码:
import numpy as np
from sklearn.datasets import make_blobs
def generateDataset(k, dimensions, n_samples):
X, y_true = make_blobs(n_samples = n_samples, centers = k, n_features= dimensions, cluster_std = 1.1)
return X, y_true
X, y_true = generateDataset(3,2,10000)
def partition(data):
if data.size != 0:
minX = np.min(data[:,0])
maxX = np.max(data[:,0])
minY = np.min(data[:,1])
maxY = np.max(data[:,1])
middleX = (maxX + minX)/2
middleY = (maxY + minY)/2
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
parts2 = np.array([i for i in data if i[0] > middleX and i[1] > middleY])
parts3 = np.array([i for i in data if i[0] < middleX and i[1] < middleY])
parts4 = np.array([i for i in data if i[0] > middleX and i[1] < middleY])
parts = np.array([parts1, parts2, parts3, parts4])
return parts
else:
return np.array([[], [], [], []])
part_data = partition(X)
for i in range(6):
if i >= 1:
part_data = np.hstack([partition(d) for d in part_data if np.shape(partition(d)) != (4,0)])
当我第一次读到这个问题时,我以为你在尝试 hstack
形状为 (4,0), (4,1,2) or (4,2,2)
的数组。但是根据评论,似乎也有形状 (4,) 数组。
4
部分来自连接4个元素
parts = np.array([parts1, parts2, parts3, parts4])
每一个都是表达式的结果:
parts1 = np.array([i for i in data if i[0] < middleX and i[1] > middleY])
您没有提供 data
的示例(不要指望我们从您的代码中重新创建它!),甚至没有 parts
.[=45= 的示例]
当我构造一个示例二维数组时,猜测什么会起作用:
In [18]: data = np.array([[1,3],[2,4],[3,1]])
In [19]: [i for i in data] # iterate on the rows
Out[19]: [array([1, 3]), array([2, 4]), array([3, 1])]
各种'range'测试:
In [20]: [i for i in data if i[0]<2 and i[1]>2]
Out[20]: [array([1, 3])]
In [21]: np.array(_)
Out[21]: array([[1, 3]])
In [22]: _.shape
Out[22]: (1, 2)
In [23]: [i for i in data if i[0]<2 and i[1]>3]
Out[23]: []
In [24]: [i for i in data if i[0]<2 and i[1]>1]
Out[24]: [array([1, 3])]
In [25]: [i for i in data if i[0]<1 and i[1]>1]
Out[25]: []
In [26]: [i for i in data if i[0]<3 and i[1]>1]
Out[26]: [array([1, 3]), array([2, 4])]
In [27]: np.array([i for i in data if i[0]<3 and i[1]>1])
Out[27]:
array([[1, 3],
[2, 4]])
In [29]: np.array([i for i in data if i[0]<3 and i[1]>3])
Out[29]: array([[2, 4]])
所以我可以获得一个 parts
数组,它是 (0,)、(1,2) 或 (2,2)(或更多的第一维)。
将其中的 4 个加入一个数组并得到一个 (4,1,2) 等。但是等等,这 4 个测试中的每一个都可以给出不同大小的数组,在这种情况下 np.array(parts....)
将产生一个 object
形状为 (4,) 的 dtype 数组。
这是怎么回事?您混合了大部分 (4,) 对象 dtype 数组以及一些 (4,0) 和 (4,n,2) 形状的数字 dtype 数组?
除了完整的代码或最小的示例,我们还应该要求您显示您正在尝试的列表 hstack
:
[partition(d) for d in part_data if np.shape(partition(d)) != (4,0)]
让我们尝试从这些示例结果中的 4 个创建 partition
数组:
In [46]: [Out[20],Out[27],Out[25],Out[29]]
Out[46]:
[[array([1, 3])],
array([[1, 3],
[2, 4]]),
[],
array([[2, 4]])]
In [47]: x1=np.array([Out[20],Out[27],Out[25],Out[29]])
<ipython-input-47-b04a5e3fb51c>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
x1=np.array([Out[20],Out[27],Out[25],Out[29]])
In [48]: x1
Out[48]:
array([list([array([1, 3])]), array([[1, 3],
[2, 4]]), list([]), array([[2, 4]])],
dtype=object)
你收到 ragged array
警告了吗?请注意,结果数组是 (4,) object dtype.
如果所有部分都是相同的形状,例如 (1,2):
In [49]: x2=np.array([Out[29],Out[29],Out[29],Out[29]])
In [50]: x2.shape
Out[50]: (4, 1, 2)
In [51]: x2
Out[51]:
array([[[2, 4]],
[[2, 4]],
[[2, 4]],
[[2, 4]]])
或 (4,0)
In [54]: x3=np.array([Out[23],Out[23],Out[23],Out[23]])
In [55]: x3
Out[55]: array([], shape=(4, 0), dtype=float64)
In [56]: x4=np.array([Out[27],Out[27],Out[27],Out[27]])
In [57]: x4.shape
Out[57]: (4, 2, 2)
即使没有 (4,0) 我们也会得到尺寸不匹配:
In [59]: np.hstack((x1,x2,x4))
Traceback (most recent call last):
Input In [59] in <cell line: 1>
np.hstack((x1,x2,x4))
File <__array_function__ internals>:180 in hstack
File /usr/local/lib/python3.8/dist-packages/numpy/core/shape_base.py:343 in hstack
return _nx.concatenate(arrs, 0)
File <__array_function__ internals>:180 in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 1 has 3 dimension(s)
我们可以将 (4,) 中的几个连接成一个新的对象 dtype 数组:
In [61]: np.hstack((x1,x1,x1)).shape
Out[61]: (12,)
关键问题是 np.array((part1,part2,...))
不是制作 (4,) 对象 dtype 数组的可靠方法。有时如果生成 (4,) 并带有警告,有时它会生成 (4,0) 或 (4,n,2)。掩饰 ragged warning
你把你自己和我们都搞糊涂了!
如果我们定义一个辅助函数,我们就可以可靠地创建一个对象 dtype 数组,即使输入的形状完全相同:
In [62]: def foo(*args):
...: res = np.empty(len(args),object)
...: res[:] = args
...: return res
...:
用它重新创建 4 个部分:
In [63]: x1 = foo([Out[29],Out[29],Out[29],Out[29]])
In [64]: x1.shape,x1.dtype
Out[64]: ((1,), dtype('O'))
In [65]: x1 = foo(Out[29],Out[29],Out[29],Out[29])
In [66]: x1.shape, x1.dtype
Out[66]: ((4,), dtype('O'))
In [67]: x2=foo(Out[29],Out[29],Out[29],Out[29])
In [68]: x2.shape, x2.dtype
Out[68]: ((4,), dtype('O'))
In [69]: x3=foo(Out[23],Out[23],Out[23],Out[23])
In [70]: x3.shape, x3.dtype
Out[70]: ((4,), dtype('O'))
In [71]: x4=foo(Out[27],Out[27],Out[27],Out[27])
In [72]: x4.shape, x4.dtype
Out[72]: ((4,), dtype('O'))
In [73]: arr = np.hstack((x1,x2,x3,x4))
In [74]: arr.shape
Out[74]: (16,)
生成的数组有点乱,但值得一看。这真的是您想要的并且能够使用的吗:
In [75]: arr
Out[75]:
array([array([[2, 4]]), array([[2, 4]]), array([[2, 4]]), array([[2, 4]]),
array([[2, 4]]), array([[2, 4]]), array([[2, 4]]), array([[2, 4]]),
list([]), list([]), list([]), list([]), array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]), array([[1, 3],
[2, 4]]), array([[1, 3],
[2, 4]])], dtype=object)
等效列表可能同样有用:
In [76]: arr.tolist()
Out[76]:
[array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
array([[2, 4]]),
[],
[],
[],
[],
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]]),
array([[1, 3],
[2, 4]])]
输入全部为空列表的 x3
情况可能需要一些改进:
In [80]: x3
Out[80]: array([list([]), list([]), list([]), list([])], dtype=object)
编辑
您添加的示例数组是:
[array([[3.95348068, 4.74190848]])
array([[4.47174131, 4.67345222],
[4.73856072, 4.68464296]])
array([], dtype=float64)
array([[4.48952751, 4.38898038],
[4.47734611, 4.34300488]])]
即(4,)(不是(4,0)或(4,1)),和object
dtype。这很像一个列表,包含对 4 个数组的引用。这些阵列的形状不同,(1,2),(2,2),(0,),(2,2)
。由于不同的形状,它只能制作一个对象 dtype 数组(带有参差不齐的数组警告)。
下面的示例是 (4,1,2),通过将 np.array
应用于 4 个形状均为 (1,2) 的数组的列表而制成。 np.array
优先制作多维数值数组。从该列表创建一个 (4,) 对象数组需要特殊操作,如我在 foo
函数中所示。