[英]How to construct an np.array with fromiter
我试图通过从python生成器中取样来构造一个np.array
,每次调用next
会生成一行数组。 以下是一些示例代码:
import numpy as np
data = np.eye(9)
labels = np.array([0,0,0,1,1,1,2,2,2])
def extract_one_class(X,labels,y):
""" Take an array of data X, a column vector array of labels, and one particular label y. Return an array of all instances in X that have label y """
return X[np.nonzero(labels[:] == y)[0],:]
def generate_points(data, labels, size):
""" Generate and return 'size' pairs of points drawn from different classes """
label_alphabet = np.unique(labels)
assert(label_alphabet.size > 1)
for useless in xrange(size):
shuffle(label_alphabet)
first_class = extract_one_class(data,labels,label_alphabet[0])
second_class = extract_one_class(data,labels,label_alphabet[1])
pair = np.hstack((first_class[randint(0,first_class.shape[0]),:],second_class[randint(0,second_class.shape[0]),:]))
yield pair
points = np.fromiter(generate_points(data,labels,5),dtype = np.dtype('f8',(2*data.shape[1],1)))
extract_one_class
函数返回数据子集:属于一个类标签的所有数据点。 我想有点是np.array
与shape = (size,data.shape[1])
目前,上面的代码段会返回错误:
ValueError: setting an array element with a sequence.
fromiter
的文档声称返回一维数组。 还有一些人使用fromiter来构建numpy中的记录数组(例如http://iam.al/post/21116450281/numpy-is-my-homeboy )。
假设我能以这种方式生成数组,那么我是不是很明显? 或者我的numpy不太正确?
正如您所注意到的, np.fromiter
的文档解释了该函数创建了一维数组。 您将无法以这种方式创建2D数组,并且@unutbu方法返回您之后重塑的一维数组是肯定的。
但是,您确实可以使用fromiter
创建结构化数组,如下所示:
>>> import itertools
>>> a = itertools.izip((1,2,3),(10,20,30))
>>> r = np.fromiter(a,dtype=[('',int),('',int)])
array([(1, 10), (2, 20), (3, 30)],
dtype=[('f0', '<i8'), ('f1', '<i8')])
但是看, r.shape=(3,)
,也就是说, r
实际上只是一维记录数组,每条记录由两个整数组成。 因为所有字段都具有相同的dtype
,所以我们可以将r
视为2D数组
>>> r.view((int,2))
array([[ 1, 10],
[ 2, 20],
[ 3, 30]])
所以,是的,你可以尝试使用np.fromiter
与dtype
类似[('',int)]*data.shape[1]
你会得到长度的一维数组size
,然后你可以查看这个数组as ((int, data.shape[1]))
。 您可以使用浮点数而不是整数,重要的是所有字段都具有相同的dtype。
如果你真的想要它,你可以使用一些相当复杂的dtype
。 例如,考虑一下
r = np.fromiter(((_,) for _ in a),dtype=[('',(int,2))])
在这里,你得到一个带有1个字段的1D结构化数组,该字段由2个整数数组组成。 注意使用(_,)
来确保每个记录都作为元组传递(否则为np.fromiter
)。 但是你需要那种复杂性吗?
另请注意,如您事先知道数组的长度(它的size
),您应该使用np.fromiter
的counter
可选参数来提高效率。
您可以修改generate_points
以generate_points
单个浮点数而不是np.arrays,使用np.fromiter
形成一维数组,然后使用.reshape(size, -1)
使其成为二维数组。
points = np.fromiter(
generate_points(data,labels,5)).reshape(size, -1)
根据这里的一些建议,我想出了一个相当普遍的numpy.fromiter()
替代品,它满足了OP的要求:
import numpy as np
def fromiter(iterator, dtype, *shape):
"""Generalises `numpy.fromiter()` to multi-dimesional arrays.
Instead of the number of elements, the parameter `shape` has to be given,
which contains the shape of the output array. The first dimension may be
`-1`, in which case it is inferred from the iterator.
"""
res_shape = shape[1:]
if not res_shape: # Fallback to the "normal" fromiter in the 1-D case
return np.fromiter(iterator, dtype, shape[0])
# This wrapping of the iterator is necessary because when used with the
# field trick, np.fromiter does not enforce consistency of the shapes
# returned with the '_' field and silently cuts additional elements.
def shape_checker(iterator, res_shape):
for value in iterator:
if value.shape != res_shape:
raise ValueError("shape of returned object %s does not match"
" given shape %s" % (value.shape, res_shape))
yield value,
return np.fromiter(shape_checker(iterator, res_shape),
[("_", dtype, res_shape)], shape[0])["_"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.