selecting array elements with a logical array 
Author Message
 selecting array elements with a logical array

Hi all,
I suspect this is a stupid question, but I've got myself stuck. I have
a two dimensional array of data and I want to extract the elements
from each column where a second one dimensional array is between
certain limits. To explain further, the following function does what I
want. Here, x is a one dimensional array specifying the grid on which
each column of my data array is based. lims is a 2-element array
containing the lower and upper limits between which I want to select
from the grid and array is the two dimensional data array.
Note that the elements of x between lims may not be contigous. This
function works, but it seems a bit heavy handed. At first I thought I
should be able to just subscript the array like array(iis,:), but that
doesn't work (I guess the logicals are converted to integers right?).
Is there a simpler way to do this. I would have though it is quite
common. Thanks for any help!

Best regards,
John

    function take(x, lims, array)
        real, allocatable, dimension(:,:) :: take
        real, dimension(:), intent(in) :: x
        real, dimension(2), intent(in) :: lims
        real, dimension(:,:), intent(in) :: array
        logical, dimension(size(x)) :: iis
        integer nc
        nc = size(array(1,:))
        iis = (x >= lims(1)) .and. (x <= lims(2))
        allocate(take(count(iis),nc))
        take = reshape(pack(array, spread(iis, 2, nc)), [count(iis),
nc])
    end function take



Sat, 10 Apr 2010 03:31:57 GMT  
 selecting array elements with a logical array

Quote:
> Hi all,
> I suspect this is a stupid question, but I've got myself stuck. I have
> a two dimensional array of data and I want to extract the elements
> from each column where a second one dimensional array is between
> certain limits. To explain further, the following function does what I
> want. Here, x is a one dimensional array specifying the grid on which
> each column of my data array is based. lims is a 2-element array
> containing the lower and upper limits between which I want to select
> from the grid and array is the two dimensional data array.
> Note that the elements of x between lims may not be contigous. This
> function works, but it seems a bit heavy handed. At first I thought I
> should be able to just subscript the array like array(iis,:), but that
> doesn't work (I guess the logicals are converted to integers right?).
> Is there a simpler way to do this. I would have though it is quite
> common. Thanks for any help!

> Best regards,
> John

>     function take(x, lims, array)
>         real, allocatable, dimension(:,:) :: take
>         real, dimension(:), intent(in) :: x
>         real, dimension(2), intent(in) :: lims
>         real, dimension(:,:), intent(in) :: array
>         logical, dimension(size(x)) :: iis
>         integer nc
>         nc = size(array(1,:))
>         iis = (x >= lims(1)) .and. (x <= lims(2))
>         allocate(take(count(iis),nc))
>         take = reshape(pack(array, spread(iis, 2, nc)), [count(iis),
> nc])
>     end function take

what about:
forall(j=1:nc) take(:,j) = pack(array(:,j),iis)


Sat, 10 Apr 2010 03:44:43 GMT  
 selecting array elements with a logical array

Quote:

> At first I thought I
> should be able to just subscript the array like array(iis,:), but that
> doesn't work (I guess the logicals are converted to integers right?).

Huh? No, the logicals aren't converted into anything. The form above
isn't a valid form, as you found out, so it pretty much doesn't make
sense to say what happens to it; nothing happens to it. Perhaps you mean
to say something like that the logicals would have to be integers for
this form to make sense instead of that the logicals "are converted" to
integers.

Quote:
> Is there a simpler way to do this.
>     function take(x, lims, array)
>         real, allocatable, dimension(:,:) :: take
>         real, dimension(:), intent(in) :: x
>         real, dimension(2), intent(in) :: lims
>         real, dimension(:,:), intent(in) :: array
>         logical, dimension(size(x)) :: iis
>         integer nc
>         nc = size(array(1,:))
>         iis = (x >= lims(1)) .and. (x <= lims(2))
>         allocate(take(count(iis),nc))
>         take = reshape(pack(array, spread(iis, 2, nc)), [count(iis),
> nc])
>     end function take

Well, simplicity is a bit in the mind of the beholder. That being
said...

You've got 4 executable statements. I can't see much to improve in the
first 3. For the last one, I think you have the central part down in
using the pack intrinsic, but I personally find the spread and reshape
stuff a bit hard to follow. (In fact I'm just going to assume I
understand it correctly; I'd have to go through it more carefully to be
sure it was correct.)

I'd dispense with the spread/reshape bit by using a loop as in

  do i = 1 , nc
    take(:,i) = pack(array(:,i),iis)
  end do

I can see what is going on there, while I'd have to carefully study the
spread/reshape thng to even be sure it was right.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain



Sat, 10 Apr 2010 04:04:33 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Shifting array element & regex on array element

2. Arrays: Build array in multiple for loops or replace array elements

3. print select elements from array

4. Array selecting elements

5. Selecting elements of an array using property nodes

6. How to select array elements?

7. HELP: Bit-select on array element???

8. f90 array features for logical arrays

9. Access Array Elements by Arrays Reference

10. for every element of array find bounds in another array

11. Array and creation of the elements of the array

12. Adjustable array dimensions specified via array element?

 

 
Powered by phpBB® Forum Software