Ranks all samples such that the smallest value obtains rank 1 and the largest rank n. Handles tied ranks and assigns average rank to tied elements within one group of tied elements.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=wp), | intent(in) | :: | x(:) |
x array |
||
real(kind=wp), | intent(out), | allocatable | :: | ranks(:) |
ranks of x |
pure subroutine s_utl_rank(x, ranks) ! ==== Description !! Ranks all samples such that the smallest value obtains rank 1 !! and the largest rank n. Handles tied ranks and assigns average !! rank to tied elements within one group of tied elements. ! ==== Declarations real(wp) , intent(in) :: x(:) !! x array real(wp) , allocatable, intent(out) :: ranks(:) !! ranks of x integer(i4), allocatable :: idx(:) !! index vector to sort x real(wp) :: rank_sum !! sum of tied ranks integer(i4) :: cnt !! counter integer(i4) :: n !! size of x integer(i4) :: i, j, k !! loop control & flexible ! ==== Instructions ! allocate n = size(x) allocate(idx(n)) allocate(ranks(n)) ! ---- create index vector ! create index vector do i = 1, n idx(i) = i enddo ! sort index based on x do i = 2, n do j = i, 2, -1 if (x(idx(j)) .lt. x(idx(j-1))) then k = idx(j) idx(j) = idx(j-1) idx(j-1) = k else exit endif enddo enddo ! ---- get rank sums ! assign ranks (with tie averaging) i = 1 do while (i .le. n) ! initialise rank sum and reset counter for tie group rank_sum = real(i, kind=wp) cnt = 1 ! check for ties do j = i + 1, n if (x(idx(j)) .eq. x(idx(i))) then rank_sum = rank_sum + real(j, kind=wp) cnt = cnt + 1 else exit endif enddo ! average rank for tie group rank_sum = rank_sum / real(cnt, kind=wp) ! assign average rank to all tied elements do k = i, i + cnt - 1 ranks(idx(k)) = rank_sum enddo ! advance to next group i = i + cnt enddo ! deallocate deallocate(idx) end subroutine s_utl_rank