Function to calculate the median value of a series.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=R8), | intent(in), | dimension(:) | :: | tab |
series 1D array |
|
logical(kind=I4), | intent(in), | optional, | dimension(:) | :: | mask |
mask |
real(kind=R8), | intent(out) | :: | md |
result: series median value |
subroutine calc_median(tab, mask, md) !================================================================================================ !! Function to calculate the median value of a series. !! !! + Input array containing the values for which the median is to be calculated !! + Optional mask to include/exclude certain values from the array !! + Output: the calculated median value !------------------------------------------------------------------------------------------------ implicit none real (kind=R8), intent(in ), dimension(:) :: tab !! *series 1D array* logical(kind=I4), intent(in ), dimension(:), optional :: mask !! *mask* real (kind=R8), intent(out) :: md !! *result: series median value* integer(kind=I4) :: lg, nz ! lg: size of the tab array; nz: number of elements to consider integer(kind=I4) :: i, ii ! i: loop counter; ii: counter for tab_tmp real(kind=R8), allocatable, dimension(:) :: tab_tmp ! Temporary array to store filtered values md = 0._R8 ! Initialize the median value to 0 lg = size( tab ) ! Get the size of the input array nz = lg ! Initialize the number of elements to lg if ( present(mask) ) then ! Check if a mask is provided nz = count( mask ) ! Count the number of true elements in the mask allocate( tab_tmp(1:nz) ) ! Allocate memory for the temporary array based on the number of elements to consider ii = 0 ! Initialize the counter for tab_tmp do i = 1, lg ! Loop through each element of the input array if ( mask(i) ) then ! If the element is included in the mask ii = ii + 1 ! Increment the counter tab_tmp(ii) = tab(i) ! Copy the corresponding value into the temporary array endif enddo if (ii /= nz) stop 'error calc_median' ! Check if the number of copied elements matches nz; if not, stop the program else ! If no mask is provided tab_tmp = tab ! Copy the input array into tab_tmp endif if (nz == 1) then ! If only one element is present md = tab_tmp(1) ! The median is the single element return ! Exit the subroutine endif if (nz == 2) then ! If two elements are present md = 0.5_R8*(tab_tmp(1) + tab_tmp(2)) ! The median is the average of the two elements return ! Exit the subroutine endif call sort_array2(tab_inout = tab_tmp(1:nz), n = nz) ! Call a subroutine to sort the temporary array if ( mod(nz, 2) == 0 ) then ! Check if the number of elements is even md = 0.5_R8 * ( tab_tmp( nz/2 ) + tab_tmp( nz/2 + 1) ) ! The median is the average of the two middle elements else ! If the number of elements is odd md = tab_tmp( (nz-1)/2 ) ! The median is the middle element endif deallocate( tab_tmp ) ! Free the allocated memory for tab_tmp return ! Exit the subroutine endsubroutine calc_median