У мене є такий код:
r = numpy.zeros(shape = (width, height, 9))
Він створює width x height x 9
матрицю, заповнену нулями. Натомість я хотів би знати, чи існує функція чи спосіб їх ініціалізації, а не NaN
просто.
У мене є такий код:
r = numpy.zeros(shape = (width, height, 9))
Він створює width x height x 9
матрицю, заповнену нулями. Натомість я хотів би знати, чи існує функція чи спосіб їх ініціалізації, а не NaN
просто.
Відповіді:
Вам рідко потрібні петлі для векторних операцій в нуме. Ви можете створити неініціалізований масив і призначити всі записи одночасно:
>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Я приурочив альтернативи a[:] = numpy.nan
тут і a.fill(numpy.nan)
як опублікував Блаєнк:
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan"
10000 loops, best of 3: 88.8 usec per loop
Часи показують перевагу ndarray.fill(..)
як більш швидку альтернативу. ОТОХ, мені подобається реалізація зручності numpy, де ви можете призначити значення цілим фрагментам у той час, намір коду дуже зрозумілий.
Зауважимо, що ndarray.fill
виконує свою операцію на місці, такnumpy.empty((3,3,)).fill(numpy.nan)
замість цього повернеться None
.
a = numpy.empty((3, 3,)) * numpy.nan
. Він fill
приділяється часу швидше, але повільніше, ніж метод призначення, але це oneliner !!
.fill()
методу, але різниця в швидкостях зводиться практично до нічого, оскільки масиви збільшуються.
np.empty([2, 5])
створює масив, значитьfill()
змінює цей масив на місці, але не повертає копію чи посилання. Якщо ви хочете зателефонувати np.empty(2, 5)
по імені ("призначити змінній"), це потрібно зробити перед тим, як зробити на ньому операції на місці. Те ж саме відбувається, якщо ви робите [1, 2, 3].insert(1, 4)
. Список створюється і вставляється 4, але неможливо отримати посилання на список (і, таким чином, можна припустити, що було зібрано сміття). На незмінних даних, таких як рядки, копія повертається, тому що ви не можете працювати на місці. Панди можуть робити і те, і інше.
Інший варіант - використання numpy.full
, опція, доступна в NumPy 1.8+
a = np.full([height, width, 9], np.nan)
Це досить гнучко, і ви можете заповнити його будь-яким іншим номером, який хочете.
full
призначено. np.empy((x,y))*np.nan
- хороший підбіг (і сумісність для старих версій numpy).
fill
python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop
python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop
Я порівняв запропоновані альтернативи щодо швидкості та виявив, що для достатньо великих векторів / матриць для заповнення всі альтернативи, за винятком val * ones
і array(n * [val])
є однаково швидкими.
Код для відтворення сюжету:
import numpy
import perfplot
val = 42.0
def fill(n):
a = numpy.empty(n)
a.fill(val)
return a
def colon(n):
a = numpy.empty(n)
a[:] = val
return a
def full(n):
return numpy.full(n, val)
def ones_times(n):
return val * numpy.ones(n)
def list(n):
return numpy.array(n * [val])
perfplot.show(
setup=lambda n: n,
kernels=[fill, colon, full, ones_times, list],
n_range=[2 ** k for k in range(20)],
logx=True,
logy=True,
xlabel="len(a)",
)
numpy.full(n, val)
повільніше , ніж , a = numpy.empty(n) .. a.fill(val)
так як він робить те ж саме всередині
Ви знайомі? numpy.nan
?
Ви можете створити власний метод, наприклад:
def nans(shape, dtype=float):
a = numpy.empty(shape, dtype)
a.fill(numpy.nan)
return a
Тоді
nans([3,4])
виведе
array([[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN]])
Я знайшов цей код у потоці списку розсилки .
Ви завжди можете використовувати множення, якщо не одразу згадати .empty
або .full
методи:
>>> np.nan * np.ones(shape=(3,2))
array([[ nan, nan],
[ nan, nan],
[ nan, nan]])
Звичайно, він також працює з будь-яким іншим числовим значенням:
>>> 42 * np.ones(shape=(3,2))
array([[ 42, 42],
[ 42, 42],
[ 42, 42]])
Але прийнята відповідь @ u0b34a0f6ae - в 3 рази швидше (цикли процесора, а не цикли мозку для запам'ятовування синтаксису нуме;):
$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)laneh@predict:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop
Інша альтернатива - це numpy.broadcast_to(val,n)
це повернення в постійний час незалежно від розміру, а також є найбільш ефективною пам'яттю (повертає вигляд повторного елемента). Застереження полягає в тому, що повернене значення є лише для читання.
Нижче наводиться порівняння результатів роботи всіх інших методів, які були запропоновані, використовуючи той самий орієнтир, що і у відповіді Ніко Шльомера .
Як було сказано, numpy.empty () - це шлях. Однак для об’єктів fill () може не робити саме те, що, на вашу думку, робиться:
In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)
Один із способів, наприклад, може бути:
In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)
Ще одна можливість, поки не згадана тут, - це використовувати плитку NumPy:
a = numpy.tile(numpy.nan, (3, 3))
Також дає
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Я не знаю про порівняння швидкості.
np.nan
виходить не так, коли переходить до int.