ryanjdillon
ryanjdillon

Reputation: 18978

Fortran equivalent of numpy.where() function?

I would like to do something like this in Fortran:

program where

real :: a(6) = (/ 4, 5, 6, 7, 8, 9 /)

print *, a(a>7)

end program

In Python I would typically do this with NumPy like this:

import numpy

a = numpy.array([ 4, 5, 6, 7, 8, 9])

print a[numpy.where(a>7)]

#or 

print a[a>7]

I've played around, but nothing has worked thus far, but I'm guessing it is fairly simple.

Upvotes: 3

Views: 1301

Answers (3)

music_piano
music_piano

Reputation: 698

You can find a related topic here: Better way to mask a Fortran array?

I think both where and merge can do the task.

In python, where has the ability to assign different value according to the mask, for example

a = np.array([4, 5, 6, 7, 8, 9])
b = np.where(a>7, 1, -1)

b will be array([-1, -1, -1, -1, 1, 1])

In Fortran, the equivalent of this is merge

real :: a(6) = (/ 4, 5, 6, 7, 8, 9 /)
real, allocatable :: b(:)
b = merge(1,-1,a>7)
print*, b
end

The MERGE function chooses alternative values based on the value of a mask. http://www.lahey.com/docs/lfpro78help/F95ARMERGEFn.htm

where can also do this, but it is slightly more complicated.

real :: a(6) = (/ 4, 5, 6, 7, 8, 9 /)
real, allocatable :: b(:)
b = a
where (a>7)
  b = 1
else where
  b = -1
end where
print*, b
end

a short version is this

b = a
b = -1
where (a>7) b = 1

You can find more information of where here: http://www.personal.psu.edu/jhm/f90/statements/where.html

Upvotes: 1

francescalus
francescalus

Reputation: 32396

I'll extend slightly the answer by @VladimirF as I suspect you don't want to limit yourself to the exact print example.

a>7 returns a logical array corresponding to a with .true. at index where the condition is met, .false. otherwise. The pack intrinsic takes such a mask and returns an array with those elements with .true. in the mask.

However, you can do other things with the mask which may fit under your numpy.where desire. For example, there is the where construct (and where statement) and the merge intrinsic. Further you can use pack again with the mask to get the indices and do more involved manipulations.

Upvotes: 5

program where

real :: a(6) = (/ 4, 5, 6, 7, 8, 9 /)

print *, pack(a,a>7)

end program

Upvotes: 4

Related Questions