comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: Ordered index array
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: Ordered index array [message #45416] Thu, 08 September 2005 07:51
Emmanuel Christophe is currently offline  Emmanuel Christophe
Messages: 11
Registered: March 2004
Junior Member
Thanks to you both, the solution proposed by Paolo does exactly what I
wanted (I don't want gaps in the "rankings") and this is fast enough for
my case.

Thanks again,
Emmanuel



David Fanning a écrit :
> Paolo Grigis writes:
>
>
>>> Then,
>>>
>>> IDL> a=[3,3,1,2,3,2,2,1,2,3]
>>> IDL> Print, a
>>> 1 1 3 4 1 4 4 3 4 1
>>
>> Well, I guess this depends on whether the original poster minds having
>> gaps in the "rankings" (no element with "rank" 2 in your example)...
>
>
> It's like golf: "tied for first and third". :-)
>
> Cheers,
>
> David
>
Re: Ordered index array [message #45419 is a reply to message #45416] Thu, 08 September 2005 06:55 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
Paolo Grigis writes:

>> Then,
>>
>> IDL> a=[3,3,1,2,3,2,2,1,2,3]
>> IDL> Print, a
>> 1 1 3 4 1 4 4 3 4 1
>
> Well, I guess this depends on whether the original poster minds having
> gaps in the "rankings" (no element with "rank" 2 in your example)...

It's like golf: "tied for first and third". :-)

Cheers,

David

--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Re: Ordered index array [message #45420 is a reply to message #45419] Thu, 08 September 2005 06:51 Go to previous message
Paolo Grigis is currently offline  Paolo Grigis
Messages: 171
Registered: December 2003
Senior Member
David Fanning wrote:
> Paolo Grigis writes:
>
> [...]
>
> Humm. Maybe I'm missing something (I haven't had my coffee yet),
> but couldn't this be solved with the original code I wrote by
> changing these two lines:
>
> ; Create index array and output array.
> b = Indgen(N_Elements(a))+ 1
> c = Intarr(N_Elements(a))
>
> To these:
>
> ; Create index array and output array.
> b = Indgen(N_Elements(a) > N_Elements(h)) + 1
> c = Intarr(N_Elements(a) > N_Elements(h))
>
> Then,
>
> IDL> a=[3,3,1,2,3,2,2,1,2,3]
> IDL> Print, a
> 1 1 3 4 1 4 4 3 4 1

Well, I guess this depends on whether the original poster minds having
gaps in the "rankings" (no element with "rank" 2 in your example)...

Ciao,
Paolo


>
> Cheers,
>
> David
>
>
Re: Ordered index array [message #45422 is a reply to message #45420] Thu, 08 September 2005 06:08 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
David Fanning writes:

> Then,
>
> IDL> a=[3,3,1,2,3,2,2,1,2,3]
> IDL> Print, a
> 1 1 3 4 1 4 4 3 4 1

Well, I'll go get my coffee now, but I think
you know this should be:

IDL> a=[3,3,1,2,3,2,2,1,2,3]
IDL> Print, Test(a)
1 1 3 4 1 4 4 3 4 1

Cheers,

David

--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Re: Ordered index array [message #45424 is a reply to message #45422] Thu, 08 September 2005 06:02 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
Paolo Grigis writes:

> But this will fail if 'a' has more elements than the number of
> its different values, for instance a=[3,3,1,2,3,2,2,1,2,3].
>
> One could try this:
>
> PRO test
>
> a=[3,3,1,2,3,2,2,1,2,3]
>
> b=a
> c=intarr(n_elements(a))
>
> h=histogram(a,min=1,reverse_ind=ri)
>
> done=0
> rank=1
> WHILE NOT done DO BEGIN
> actual_value=b[0]
> ind_actual_value=ri[ri[actual_value-1]:ri[actual_value]-1]
> c[ind_actual_value]=rank
> rank=rank+1
> indremove=where(b NE actual_value,count)
> IF count GT 0 THEN b=b[indremove] ELSE done=1
> ENDWHILE
>
> print,a
> print,c
>
> END
>
>
> but it will get inefficient as the numbers of different values
> in 'a' grows, as the code in the loop get called more and more
> times...

Humm. Maybe I'm missing something (I haven't had my coffee yet),
but couldn't this be solved with the original code I wrote by
changing these two lines:

; Create index array and output array.
b = Indgen(N_Elements(a))+ 1
c = Intarr(N_Elements(a))

To these:

; Create index array and output array.
b = Indgen(N_Elements(a) > N_Elements(h)) + 1
c = Intarr(N_Elements(a) > N_Elements(h))

Then,

IDL> a=[3,3,1,2,3,2,2,1,2,3]
IDL> Print, a
1 1 3 4 1 4 4 3 4 1

Cheers,

David


--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Re: Ordered index array [message #45428 is a reply to message #45424] Thu, 08 September 2005 05:30 Go to previous message
Paolo Grigis is currently offline  Paolo Grigis
Messages: 171
Registered: December 2003
Senior Member
Emmanuel Christophe wrote:
> Thanks Paolo,
> Your function does exactly what I want, but my problem is precisely that
> I need to do it on huge array (300 000 elements at least), that why i'm
> looking for a more 'IDL' way to do it :)
>
> Emmanuel
Ok, let's do it. We'll use a loop, but this should not be too
bad as long as you don't have more than a few million elements,
provided that we just do simple operations in the loop.

PRO test2

a=[1,3,3,1,2,3,2,2,1,2,3]

c=lonarr(n_elements(a))

h=histogram(a,min=1L,reverse_ind=ri)

listlowestind=replicate(-1L,n_elements(h))

FOR i=0L,n_elements(h)-1 DO BEGIN
IF ri[i] NE ri[i+1] THEN listlowestind[i]=ri[ri[i]]
ENDFOR

indok=where(listlowestind GT -1L,countindok)
indoffset=n_elements(listlowestind)-countindok
indsorted=(sort(listlowestind))

FOR i=0L,countindok-1 DO BEGIN
this_element=a[listlowestind[indsorted[i+indoffset]]]
c[ri[ri[this_element-1]:ri[this_element]-1]]=i+1
ENDFOR

print,c

end

The idea here is to use histogram to scout for the first occurrence
of each integer number and store it in listlowestind. We then
sort the list, such that we know which element occurs first,
and then with a second loop we fill the output array c with
the occurrences of each element, and since we have sorted the
array first, we know which rank to assign to each element.
This should be moderately efficient. I assumed that the array
a has integer elements starting from 1, if not the case, just
sum 1-min(a) to the array before performing the operation.

Ciao,
Paolo


>
>
>
>
>> But this will fail if 'a' has more elements than the number of
>> its different values, for instance a=[3,3,1,2,3,2,2,1,2,3].
>>
>> One could try this:
>>
>> PRO test
>>
>> a=[3,3,1,2,3,2,2,1,2,3]
>>
>> b=a
>> c=intarr(n_elements(a))
>>
>> h=histogram(a,min=1,reverse_ind=ri)
>>
>> done=0
>> rank=1
>> WHILE NOT done DO BEGIN
>> actual_value=b[0]
>> ind_actual_value=ri[ri[actual_value-1]:ri[actual_value]-1]
>> c[ind_actual_value]=rank
>> rank=rank+1
>> indremove=where(b NE actual_value,count)
>> IF count GT 0 THEN b=b[indremove] ELSE done=1
>> ENDWHILE
>>
>> print,a
>> print,c
>>
>> END
>>
>>
>> but it will get inefficient as the numbers of different values
>> in 'a' grows, as the code in the loop get called more and more
>> times...
>>
>> Ciao,
>> Paolo
>>
>>
>>> Cheers,
>>>
>>> David
>>>
>>>
Re: Ordered index array [message #45430 is a reply to message #45428] Thu, 08 September 2005 03:03 Go to previous message
Paolo Grigis is currently offline  Paolo Grigis
Messages: 171
Registered: December 2003
Senior Member
Emmanuel Christophe wrote:
> Thanks Paolo,
> Your function does exactly what I want, but my problem is precisely that
> I need to do it on huge array (300 000 elements at least), that why i'm
> looking for a more 'IDL' way to do it :)
The problem is not in the number of *elements* of a, but
in the number of *different values* that a can take...
but yes, if this is large, you should not use that routine.

Paolo


>
> Emmanuel
>
>
>
>
>> But this will fail if 'a' has more elements than the number of
>> its different values, for instance a=[3,3,1,2,3,2,2,1,2,3].
>>
>> One could try this:
>>
>> PRO test
>>
>> a=[3,3,1,2,3,2,2,1,2,3]
>>
>> b=a
>> c=intarr(n_elements(a))
>>
>> h=histogram(a,min=1,reverse_ind=ri)
>>
>> done=0
>> rank=1
>> WHILE NOT done DO BEGIN
>> actual_value=b[0]
>> ind_actual_value=ri[ri[actual_value-1]:ri[actual_value]-1]
>> c[ind_actual_value]=rank
>> rank=rank+1
>> indremove=where(b NE actual_value,count)
>> IF count GT 0 THEN b=b[indremove] ELSE done=1
>> ENDWHILE
>>
>> print,a
>> print,c
>>
>> END
>>
>>
>> but it will get inefficient as the numbers of different values
>> in 'a' grows, as the code in the loop get called more and more
>> times...
>>
>> Ciao,
>> Paolo
>>
>>
>>> Cheers,
>>>
>>> David
>>>
>>>
Re: Ordered index array [message #45431 is a reply to message #45430] Thu, 08 September 2005 01:58 Go to previous message
Emmanuel Christophe is currently offline  Emmanuel Christophe
Messages: 11
Registered: March 2004
Junior Member
Thanks Paolo,
Your function does exactly what I want, but my problem is precisely that
I need to do it on huge array (300 000 elements at least), that why i'm
looking for a more 'IDL' way to do it :)

Emmanuel



>
> But this will fail if 'a' has more elements than the number of
> its different values, for instance a=[3,3,1,2,3,2,2,1,2,3].
>
> One could try this:
>
> PRO test
>
> a=[3,3,1,2,3,2,2,1,2,3]
>
> b=a
> c=intarr(n_elements(a))
>
> h=histogram(a,min=1,reverse_ind=ri)
>
> done=0
> rank=1
> WHILE NOT done DO BEGIN
> actual_value=b[0]
> ind_actual_value=ri[ri[actual_value-1]:ri[actual_value]-1]
> c[ind_actual_value]=rank
> rank=rank+1
> indremove=where(b NE actual_value,count)
> IF count GT 0 THEN b=b[indremove] ELSE done=1
> ENDWHILE
>
> print,a
> print,c
>
> END
>
>
> but it will get inefficient as the numbers of different values
> in 'a' grows, as the code in the loop get called more and more
> times...
>
> Ciao,
> Paolo
>
>>
>> Cheers,
>>
>> David
>>
>>
Re: Ordered index array [message #45432 is a reply to message #45431] Thu, 08 September 2005 01:48 Go to previous message
Emmanuel Christophe is currently offline  Emmanuel Christophe
Messages: 11
Registered: March 2004
Junior Member
Sorry, my example was confusing:

if the input is
[2,2,2,2,2,2,2,2,2,5,8]
I would like an output like
[1,1,1,1,1,1,1,1,1,2,3]

The property that should be verified is the n-th symbol of the output is
either
- the same as one between 0 and (n-1)th position
- equal to max(output[0:n-1])+1

and output[0]=1

I thought also about using the reverse_indices of the histogram
function, but as it doesn't preserve the order, I'm not sure it would work.

Thanks,
Emmanuel


David Fanning a écrit :
> David Fanning writes:
>
>
>> How about this:
>>
>> PRO TEST
>> a = [3,6,2,1,2,7,1,1]
>> h = Histogram(a, Reverse_Indices=ri, Min=0)
>> b = Indgen(N_Elements(h)) + 1
>> c = Intarr(N_Elements(h))
>> FOR j=0,N_Elements(h)-1 DO BEGIN
>> IF ri[j+1] NE ri[j] THEN $
>> c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
>> ENDFOR
>> Print, c
>> END
>>
>> 1 2 3 4 3 6 4 4
>>
>> Note that your original example is wrong. :-)
>
>
> Whoops! *I* didn't use the original example either (although
> yours is still wrong!).
>
> Here is a more complete solution, using the original data:
>
> PRO TEST
> a = [3,6,2,1,2,8,1,1]
> h = Histogram(a, Reverse_Indices=ri, Min=0)
> b = Indgen(N_Elements(h)) + 1
> c = Intarr(N_Elements(h))
> FOR j=0,N_Elements(h)-1 DO BEGIN
> IF ri[j+1] NE ri[j] THEN $
> c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
> ENDFOR
> Print, c[0:N_Elements(a)-1]
> END
>
> Cheers,
>
> David
>
>
Re: Ordered index array [message #45433 is a reply to message #45432] Thu, 08 September 2005 01:22 Go to previous message
Paolo Grigis is currently offline  Paolo Grigis
Messages: 171
Registered: December 2003
Senior Member
David Fanning wrote:
> David Fanning writes:
>
>
>> How about this:
>>
>> PRO TEST
>> a = [3,6,2,1,2,7,1,1]
>> h = Histogram(a, Reverse_Indices=ri, Min=0)
>> b = Indgen(N_Elements(h)) + 1
>> c = Intarr(N_Elements(h))
>> FOR j=0,N_Elements(h)-1 DO BEGIN
>> IF ri[j+1] NE ri[j] THEN $
>> c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
>> ENDFOR
>> Print, c
>> END
>>
>> 1 2 3 4 3 6 4 4
>>
>> Note that your original example is wrong. :-)
>
>
> Whoops! *I* didn't use the original example either (although
> yours is still wrong!).
>
> Here is a more complete solution, using the original data:
>
> PRO TEST
> a = [3,6,2,1,2,8,1,1]
> h = Histogram(a, Reverse_Indices=ri, Min=0)
> b = Indgen(N_Elements(h)) + 1
> c = Intarr(N_Elements(h))
> FOR j=0,N_Elements(h)-1 DO BEGIN
> IF ri[j+1] NE ri[j] THEN $
> c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
> ENDFOR
> Print, c[0:N_Elements(a)-1]
> END
But this will fail if 'a' has more elements than the number of
its different values, for instance a=[3,3,1,2,3,2,2,1,2,3].

One could try this:

PRO test

a=[3,3,1,2,3,2,2,1,2,3]

b=a
c=intarr(n_elements(a))

h=histogram(a,min=1,reverse_ind=ri)

done=0
rank=1
WHILE NOT done DO BEGIN
actual_value=b[0]
ind_actual_value=ri[ri[actual_value-1]:ri[actual_value]-1]
c[ind_actual_value]=rank
rank=rank+1
indremove=where(b NE actual_value,count)
IF count GT 0 THEN b=b[indremove] ELSE done=1
ENDWHILE

print,a
print,c

END


but it will get inefficient as the numbers of different values
in 'a' grows, as the code in the loop get called more and more
times...

Ciao,
Paolo

>
> Cheers,
>
> David
>
>
Re: Ordered index array [message #45443 is a reply to message #45433] Wed, 07 September 2005 10:17 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
David Fanning writes:

> How about this:
>
> PRO TEST
> a = [3,6,2,1,2,7,1,1]
> h = Histogram(a, Reverse_Indices=ri, Min=0)
> b = Indgen(N_Elements(h)) + 1
> c = Intarr(N_Elements(h))
> FOR j=0,N_Elements(h)-1 DO BEGIN
> IF ri[j+1] NE ri[j] THEN $
> c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
> ENDFOR
> Print, c
> END
>
> 1 2 3 4 3 6 4 4
>
> Note that your original example is wrong. :-)

Whoops! *I* didn't use the original example either (although
yours is still wrong!).

Here is a more complete solution, using the original data:

PRO TEST
a = [3,6,2,1,2,8,1,1]
h = Histogram(a, Reverse_Indices=ri, Min=0)
b = Indgen(N_Elements(h)) + 1
c = Intarr(N_Elements(h))
FOR j=0,N_Elements(h)-1 DO BEGIN
IF ri[j+1] NE ri[j] THEN $
c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
ENDFOR
Print, c[0:N_Elements(a)-1]
END

Cheers,

David


--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Re: Ordered index array [message #45444 is a reply to message #45443] Wed, 07 September 2005 10:01 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
Emmanuel Christophe writes:

> I would like to change the values on an array according to the order
> they appear. Following this example:
>
> starting with the array
> [3,6,2,1,2,8,1,1]
> I would like to get
> [1,2,3,4,3,5,4,4]
>
> 3 being the first value seen it is affected to 1
> 6 being the second, affected to 2
> ...
>
> I guess this process is similar to lookup tables, or color tables. As I
> would like to process quite big arrays (>60000 long elements), i'm
> looking for an efficient function. I don't really know what to look for
> in IDL help to find something which could help.

How about this:

PRO TEST
a = [3,6,2,1,2,7,1,1]
h = Histogram(a, Reverse_Indices=ri, Min=0)
b = Indgen(N_Elements(h)) + 1
c = Intarr(N_Elements(h))
FOR j=0,N_Elements(h)-1 DO BEGIN
IF ri[j+1] NE ri[j] THEN $
c[ri[ri[j]:ri[j+1]-1]] = Min(b[ri[ri[j]:ri[j+1]-1]])
ENDFOR
Print, c
END

1 2 3 4 3 6 4 4

Note that your original example is wrong. :-)

Cheers,

David

--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: 2 arrays, average, missing data
Next Topic: Re: 2 arrays, average, missing data

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 19:09:41 PDT 2025

Total time taken to generate the page: 0.01479 seconds