Создать матрицу образца: проблема с дополнительными аргументами np.apply_along_axis - PullRequest
0 голосов
/ 03 февраля 2019

Я наткнулся на небольшую проблему, пытаясь создать Матрицу случайно выбранной выборки среди совокупности, используя 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 принимает несколько аргументов, я создал матрицу A, заполненную семерками (потому что я хочу сэмплы из 7 элементов из pop), чтобы аргументы размера исходили из значения каждой строки A, а аргумент aзаданный в конце a=pop.

Мне было интересно, знает ли кто-нибудь, что здесь за ошибка и как ее исправить.

Я использовал np.apply_along_axis, чтобы создать этоматрица сэмплов, потому что я бы сделал это аналогично функции apply в R, но, может быть, есть лучший способ сделать это?

1 Ответ

0 голосов
/ 03 февраля 2019

Ваша попытка использования 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]) в f5 раз и собрать результаты в массив.Временами эта версия 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 может быть полезно, когда A имеет значение 3d (или больше), и вы хотите применить функцию к одной оси и выполнить итерации по другим.Проще применить, чем:

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

, но вы создаете двумерный массив (n, 1), просто вы можете выполнить итерацию по первой оси, передав 2-ю ось (размер 1) функции.Итерация по массиву (n,) концептуально и вычислительно проще.

...