创建样本矩阵:带有np.apply_along_axis其他参数的问题

时间:2019-02-03 16:36:13

标签: python python-3.x numpy random

我偶然发现了一个小问题,试图使用numpy在人群中创建随机选择的样本矩阵。

我要创建的是一个矩阵,每行代表我的总体样本,这样我就可以一次更高效地对每个样本进行操作。

我尝试执行以下操作:

import numpy as np

l = ["L"] * 36 + ["T1"]*20 + [0]*43

pop = np.array(l)

ech = np.random.choice(a = pop, size=7, replace=False)  # This is what I want my sample to be

A = np.full((30,1),7)  # Here I want 30 samples in my matrix

np.apply_along_axis(arr=A, func1d=np.random.choice, axis=1, a = pop)

但是,出现以下错误:

TypeError: choice() got multiple values for keyword argument 'a'

由于np.random.choice函数带有多个参数,因此我创建了一个用7填充的矩阵A(因为我希望从pop中获得7个元素的样本),以便size参数来自A的每一行的值,并且一个参数由a=pop结尾。

我想知道是否有人知道这里的错误以及如何解决它。

我用过的np.apply_along_axis来创建这个样本矩阵,因为我会用R中的apply函数以类似的方式来完成,但是也许有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

您尝试使用apply_along_axis令人困惑,但是我认为您正在尝试这样做:

pop中的一个样本集:

In [110]: pop = list('abcdefgijklm')
In [111]: np.random.choice(pop, size=7, replace=False)
Out[111]: array(['g', 'm', 'f', 'l', 'c', 'i', 'k'], dtype='<U1')

作为以size作为参数的函数进行广播:

In [112]: f = lambda s: np.random.choice(pop, size=s, replace=False)

直接进行Python迭代,生成大小不同的样本:

In [113]: [f(i) for i in [3,5,4]]
Out[113]: 
[array(['j', 'b', 'l'], dtype='<U1'),
 array(['l', 'e', 'k', 'm', 'b'], dtype='<U1'),
 array(['k', 'm', 'j', 'b'], dtype='<U1')]

但是要制作示例数组,size必须相同,所以我们可以这样做:

In [114]: np.array([f(7) for _ in range(3)])
Out[114]: 
array([['a', 'f', 'm', 'd', 'e', 'l', 'j'],
       ['i', 'g', 'f', 'b', 'j', 'e', 'l'],
       ['j', 'm', 'k', 'i', 'l', 'a', 'b']], dtype='<U1')

但是由于您坚持使用apply_along_axis,因此可以采用以下方法:

In [122]: A = np.full((5,1), 7)
In [123]: np.apply_along_axis(f, 1, A)
Out[123]: 
array([['c', 'm', 'a', 'f', 'i', 'd', 'k'],
       ['j', 'm', 'k', 'd', 'b', 'l', 'g'],
       ['b', 'f', 'i', 'm', 'c', 'l', 'k'],
       ['k', 'f', 'd', 'l', 'b', 'c', 'g'],
       ['l', 'f', 'j', 'k', 'g', 'a', 'd']], dtype='<U1')

它将np.array([7])传递到f 5次,并将结果收集到一个数组中。在时间上,此apply版本比我的[113]迭代要慢一些。

要传递pop作为参数,我们必须定义一个func1d,例如:

In [135]: f = lambda s, a: np.random.choice(a, s, replace=False)
In [136]: np.apply_along_axis(f, 1, A, a=pop)
Out[136]: 
array([['j', 'd', 'b', 'f', 'c', 'l', 'k'],
       ['d', 'c', 'e', 'j', 'm', 'k', 'i'],
       ['l', 'g', 'j', 'k', 'e', 'f', 'a'],
       ['a', 'l', 'e', 'm', 'b', 'c', 'j'],
       ['j', 'e', 'g', 'f', 'l', 'd', 'a']], dtype='<U1')
apply_along_axis为3d(或更大)时,

A很有用,并且您想将一个功能应用于一个轴,然后在另一个轴上进行迭代。比以下方法更容易应用:

 for i in range...:
     for j in range ...:
         res[i,j,:] = func1d(A[i,j,:])

但是您构造了一个2d数组(n,1),只是可以在第一个轴上进行迭代,将第二个(大小为1)的轴传递给该函数。在(n,)数组上进行迭代在概念上和计算上都更简单。