Если ваша функция написана так, что она принимает целые массивы, вы можете просто передать x
и y
, чтобы они broadcast
вместе.
In [472]: x = np.linspace(10,20,10)
...: y = np.linspace(5,8,5)
In [473]: def f(x,y):
...: return (1-x)**3.2 * np.cos(y**2.31+x)
...:
Make x
(10,1 ) массив, который затем вещает с (5,) y
для получения результата (10,5):
In [474]: f(x[:,None], y)
/usr/local/bin/ipython3:2: RuntimeWarning: invalid value encountered in power
Out[474]:
array([[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]])
Все, что fromfunction
делает, генерирует indices
и передает их вашей функции:
In [478]: np.indices((3,4))
Out[478]:
array([[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2]],
[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]]])
#function(*indices...)
Если ваша функция ожидает значения, не индексы i,j
fromfunction
ничего не сделают для вас !. он просто заставляет вас использовать дополнительный уровень индексации f(x[i],y[j])
. Если ваша функция обрабатывает массивы, fromfunction
не ускоряет вычисления. И если ваша функция может принимать только скаляры, fromfunction
не работает вообще.
Почему nan
?
In [489]: f(x[0],y[0])
/usr/local/bin/ipython3:2: RuntimeWarning: invalid value encountered in double_scalars
Out[489]: nan
===
С исправлено f
:
In [494]: def f(x,y):
...: return (1+x)**3.2 * np.cos(y**2.31+x)
...:
In [495]: x,y
Out[495]:
(array([10. , 11.11111111, 12.22222222, 13.33333333, 14.44444444,
15.55555556, 16.66666667, 17.77777778, 18.88888889, 20. ]),
array([5. , 5.75, 6.5 , 7.25, 8. ]))
ix_
может использоваться для добавления измерения вещания к x
:
In [496]: np.ix_(x,y)
Out[496]:
(array([[10. ],
[11.11111111],
[12.22222222],
[13.33333333],
[14.44444444],
[15.55555556],
[16.66666667],
[17.77777778],
[18.88888889],
[20. ]]),
array([[5. , 5.75, 6.5 , 7.25, 8. ]]))
И эти массивы затем могут быть переданы в f
(как я делал в [474]):
In [497]: f(*np.ix_(x,y))
Out[497]:
array([[ 1322.50123614, -1353.39115671, -1702.96842965,
2039.59858593, 2149.99822839],
[ -1268.79441897, 1220.20345147, 572.47038806,
401.57578676, 1322.04810644],
[ -3873.89288421, 3872.45293387, 3741.19176848,
-3203.15416244, -2320.43820171],
[ -2274.83634272, 2356.4885057 , 3316.20257628,
-4368.07920439, -4932.15975126],
[ 3805.32723978, -3710.95441159, -2413.75855025,
343.98082438, -1742.79381001],
[ 7825.16462628, -7850.07869311, -7934.59775682,
7309.08041012, 5891.07144208],
[ 2696.9980712 , -2869.31389573, -4956.11491324,
7455.17663401, 9114.69519122],
[ -8800.47513177, 8651.89940176, 6527.58767232,
-2896.13626079, 1015.66697767],
[-13326.47899275, 13419.77502789, 14202.98227539,
-13981.08503081, -12233.58338808],
[ -1484.09855587, 1795.12675239, 5660.63236478,
-10620.54747276, -14370.53381538]])
Применительно к 3 массивам:
In [503]: np.ix_([100,200],[10,20,30],[1,2,3,4])
Out[503]:
(array([[[100]],
[[200]]]), array([[[10],
[20],
[30]]]), array([[[1, 2, 3, 4]]]))
производит (2,1,1), (1,3,1) и (1,1,4) массивы, которые будут транслироваться вместе для получения (2,3,4) результата.
def ff(x,y,z): return x+y+z
In [504]: ff(*_)
Out[504]:
array([[[111, 112, 113, 114],
[121, 122, 123, 124],
[131, 132, 133, 134]],
[[211, 212, 213, 214],
[221, 222, 223, 224],
[231, 232, 233, 234]]])