如何用fromiter构造一个np.array

Lee*_*aro 3 python numpy

我试图np.array通过从python生成器中取样来构造一个,每次调用时会生成一行数组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)))
Run Code Online (Sandbox Code Playgroud)

extract_one_class函数返回数据子集:属于一个类标签的所有数据点.我想有np.arrayshape = (size,data.shape[1]).目前,上面的代码段会返回错误:

ValueError: setting an array element with a sequence.
Run Code Online (Sandbox Code Playgroud)

fromiter声明返回一维数组的文档.还有一些人使用fromiter来构建numpy中的记录数组(例如http://iam.al/post/21116450281/numpy-is-my-homeboy).

假设我能以这种方式生成数组,那么我是不是很明显?或者我的numpy不太正确?

Pie*_* GM 8

正如您所注意到的,文档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')])
Run Code Online (Sandbox Code Playgroud)

但看,r.shape=(3,),就是r真的不算什么,但记录的一维数组,每个记录被由两个整数.因为所有字段都相同dtype,所以我们可以将视图r视为2D数组

>>> r.view((int,2))
array([[ 1, 10],
       [ 2, 20],
       [ 3, 30]])
Run Code Online (Sandbox Code Playgroud)

所以,是的,你可以尝试使用np.fromiter一个dtype[('',int)]*data.shape[1]:你会得到长度的一维数组size,然后你可以查看这个数组((int, data.shape[1])).您可以使用浮点数而不是整数,重要的是所有字段都具有相同的dtype.

如果你真的想要它,你可以使用一些相当复杂的dtype.例如,考虑一下

r = np.fromiter(((_,) for _ in a),dtype=[('',(int,2))])
Run Code Online (Sandbox Code Playgroud)

在这里,你得到一个带有1个字段的1D结构化数组,该字段由2个整数数组组成.注意使用(_,)以确保每个记录作为元组传递(否则np.fromiter扼流圈).但是你需要那种复杂性吗?

另请注意,正如您事先知道数组的长度(它的size),您应该使用counter可选参数np.fromiter来提高效率.


unu*_*tbu 5

您可以修改generate_points为生成单个浮点而不是 np.arrays,用于np.fromiter形成一维数组,然后用于.reshape(size, -1)使其成为二维数组。

points = np.fromiter(
    generate_points(data,labels,5)).reshape(size, -1)
Run Code Online (Sandbox Code Playgroud)