Реализация оператора Фортрана WHERE в Python - PullRequest
0 голосов
/ 07 июня 2018

Есть ли способ сделать это в Python с массивами NumPy?желательно без использования слишком много для петель.

Я знаю, numpy.where() существует, но я не уверен, как реализовать его, если его можно использовать, как в следующем фрагменте Фортрана

z_ocean=0
do i=1,nstep_yr
   where(mldclim(:,:,i).gt.z_ocean) z_ocean = mldclim(:,:,i)
end do

1 Ответ

0 голосов
/ 08 июня 2018

Подумайте, что подразумевается под оператором where в вашем коде фортрана:

"присваивайте каждому элементу z_ocean, где значение соответствующего элемента из mldclim[i, :, :] больше значения элемента в z_ocean, значение элемента из mldclim[i, :, :] "

Редактировать: Я изменил приведенное выше определение, чтобы лучше отразить тот факт, что это поэлементная операция, как указано в комментарии@ francescalus

Глядя на документацию для numpy.where(), ее можно использовать как where(*condition*, *value if true*, *value if false*).Итак, в вашем случае, что-то вроде этого:
z_ocean = np.where(mldclim[i, :, :] > z_ocean, mldclim[i, :, :], z_ocean)

Вот примеры в Python (обратите внимание, что я поменял местами порядок индексов в Python для прямого сравнения)

import numpy as np    

nstep_yr = 2    

# initialize randomly
# mldclim = np.random.rand(nstep_yr, 3, 3) - 0.5    
# use these values for fortran comparison
mldclim = np.reshape([ 0.09911714,  0.18911965,  0.30409478, -0.08548523, \
                      -0.03652424, -0.18361127,  0.49970408, -0.04139379, \
                      -0.03451338, -0.24631131,  0.35726568, -0.30630386, \
                       0.26184705,  0.01286879, -0.21745516,  0.46137956, \
                       0.40410629,  0.29996342], (nstep_yr, 3, 3) )    

# initialize and make a copies for testing...
z_ocean = np.zeros((3,3))
z_ocean_1 = np.copy(z_ocean)
z_ocean_2 = np.copy(z_ocean)    

for i in range(nstep_yr):
    # "direct translation" of your fortran code
    z_ocean = np.where(mldclim[i, :, :] > z_ocean, mldclim[i, :, :], z_ocean)
    # loop based version of @francescalus' comment
    z_ocean_1 = np.maximum(z_ocean_1, mldclim[i, :, :])    
# loop free version of @francescalus' comment
z_ocean_2 = np.maximum(z_ocean_2, np.max(mldclim, axis=0)) 

# check that all solutions are the same
assert np.allclose(z_ocean, z_ocean_1) and np.allclose(z_ocean, z_ocean_2)    

print(z_ocean.ravel())

и fortran (повторяет исходный пример кода)

program test
    implicit none

    integer, parameter :: nstep_yr = 2
    real :: mldclim(3,3,nstep_yr)
    real :: z_ocean(3,3)
    integer :: i

    mldclim = reshape([ 0.09911714,  0.18911965,  0.30409478, -0.08548523, &
                       -0.03652424, -0.18361127,  0.49970408, -0.04139379, &
                       -0.03451338, -0.24631131,  0.35726568, -0.30630386, &
                        0.26184705,  0.01286879, -0.21745516,  0.46137956, &
                        0.40410629,  0.29996342], [3, 3, 2] )

    z_ocean=0
    do i=1,nstep_yr
        where(mldclim(:,:,i).gt.z_ocean) z_ocean = mldclim(:,:,i)
    end do
    print *, z_ocean

end program test

, который дает следующий вывод:

  • python [0.09911714 0.35726568 0.30409478 0.26184705 0.01286879 0. 0.49970408 0.40410629 0.29996342]
  • fortran 9.91171375E-02 0.357265681 0.304094791 0.261847049 1.28687900E-02 0.00000000 0.499704093 0.404106289 0.299963415
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...