0

I'm trying to write a program to find the mean, median, mode of an integer array but am having some complications in finding the mode. The following is the code that I've written so far.

First, the program will prompt user to enter a value for the number of integers that will be entered followed by request to enter that number of integers. The integers are then sorted in ascending order and the mean and median are found.

The problem I am having is when I try to get the mode. I am able to count the number of occurrence of a repetitive value. By finding the value with highest occurrence, we'll be able to find Mode. But I am unsure how to do this. Is there any intrinsic function in Fortran to calculate number of occurrence of input values and the value with highest occurrence?

  PROGRAM STATISTICS
  !Created by : Rethnaraj Rambabu
  IMPLICIT NONE

  REAL, DIMENSION(:), ALLOCATABLE:: VAL
  REAL TEMP, MEDIAN
  REAL EVEN, MEAN, SUM, FMODE

  INTEGER N, I,J

  WRITE(*,*)' WHAT IS THE VALUE FOR N? '
  READ(*,*) N
  ALLOCATE(VAL(N))

  WRITE(*,*) 'ENTER THE NUMBERS'
  OPEN(1,FILE='FILE.TXT')
  READ(1,*)(VAL(I),I=1,N)
  CLOSE(1)
  WRITE(*,*) VAL

  !/---FOR SORTING----/!

  DO I=1,N-1
    DO J=1,N-1
      IF(VAL(J) > VAL(J+1)) THEN
      TEMP=VAL(J)
      VAL(J)=VAL(J+1)
      VAL(J+1)=TEMP
      END IF
    END DO
  END DO

  WRITE(*,*) VAL

  !/-----MEDIAN----/!

  IF ((N/2*2) /= N) THEN
      MEDIAN=VAL((N+1)/2)
    ELSE IF ((N/2*2) == N) THEN
      EVEN= (VAL(N/2)+VAL((N+2)/2))
      MEDIAN=EVEN/2
  END IF

  WRITE(*,*)'MEDIAN=', MEDIAN

  !/----MEAN----/
  SUM=0
  DO I=1,N
    SUM=SUM+VAL(I)
  END DO
    MEAN=SUM/N

  WRITE(*,*)'MEAN=', MEAN

  !/------MODE----/
  FMODE=1
  DO I=1,N-1
    IF (VAL(I) == VAL(I+1)) THEN
    FMODE=FMODE+1
  END IF
  END DO

  WRITE(*,*)FMODE

  END PROGRAM

The FILE.TXT contains

10 8 1 9 8 9 9 7 5 9 3 5 6

1
  • Y'know, if this was a Java question, it would be a lead-pipe cinch it was a homework assignment. It might still be one, for an engineering statistics class: there might be a few places still using FORTRAN in engineering school. Commented Jan 10, 2012 at 14:05

2 Answers 2

2

But, how to do that? Or is there any intrinsic function in Fortran to calculate number of occurrence of input values and the value with highest occurrence.

No, there is not. You'll have to calculate the mode by hand.

The following code should work (on a sorted array):

FMODE = VAL(1)
COUNT = 1
CURRENTCOUNT = 1
DO I = 2, N
    ! We are going through the loop looking for values == VAL(I-1)...
    IF (VAL(I) == VAL(I-1)) THEN
        ! We spotted another VAL(I-1), so increment the count.
        CURRENTCOUNT = CURRENTCOUNT + 1
    ELSE
        ! There are no more VAL(I-1)
        IF (CURRENTCOUNT > COUNT) THEN
            ! There were more elements of value VAL(I-1) than of value FMODE
            COUNT = CURRENTCOUNT
            FMODE = VAL(I-1)
        END IF
        ! Next we are looking for values == VAL(I), so far we have spotted one...
        CURRENTCOUNT = 1
    END
END DO
IF (CURRENTCOUNT > COUNT) THEN
    ! This means there are more elements of value VAL(N) than of value FMODE.
    FMODE = VAL(N)
END IF

Explanation:

We keep the best-so-far mode in the FMODE variable, and the count of the FMODE in the COUNT variable. As we step through the array we count the number of hits that are equal to what we are looking at now, in the CURRENTCOUNT variable.

If the next item we look at is equal to the previous, we simply increment the CURRENTCOUNT. If it's different, then we need to reset the CURRENTCOUNT, because we will now count the number of duplications of the next element.

Before we reset the CURRENTCOUNT we check if it's bigger than the previous best result, and if it is, we overwrite the previous best result (the FMODE and COUNT variables) with the new best results (whatever is at VAL(I) and CURRENTCOUNT), before we continue.

This reset doesn't happen at the end of the loop, so I inserted another check at the end in case the most frequent element happens to be the final element of the loop. In that case we overwrite FMODE, like we would have done in the loop.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi! Thanks for the quick reply. It is working perfectly. Yet, I'm still trying to understand your code. I don't understand the ELSE part and the following IF (CURRENTCOUNT > COUNT) FMODE = VAL(N) I'm just a beginner in Fortran.
@RethnarajRambabu I added some comments and an explanation, does this help?
Thanks a lot for your detailed explanation. I have understood the code now.
0

It is a bit lengthy, you could probably get rid of the optional argument, but there is an example provided here. They use the quick sort algorithm as implemented here.

Alternatively, you could use

integer function mode(arr) result(m)
  implicit none

  integer, dimension(:), intent(in) :: arr

  ! Local variables
  integer, dimension(:), allocatable :: counts
  integer :: i, astat
  character(len=128) :: error_str

  ! Initialise array to count occurrences of each value.
  allocate(counts(minval(arr):maxval(arr)), stat=astat, errmsg=error_str)
    if (astat/=0) then
      print'("Allocation of counts array failed.")'
      print*, error_str
    end if

  counts = 0

  ! Loop over inputted array, counting occurrence of each value.
  do i=1,size(arr)
      counts(arr(i)) = counts(arr(i)) + 1
  end do

  ! Finally, find the mode
  m = minloc(abs(counts - maxval(counts)),1)

end function mode

This doesn't require any sorting.

5 Comments

Thanks for your time and the code, Chris. Noted this code too :D
arr(i) could be very large, in which case allocating counts is inconvenient. It could also be negative, so you must allocate(counts(minval:maxval)). In a language with builtin hash tables I would recommend using a hash table for the counts instead, but in Fortran I think unless there is a serious bottleneck it's easiest to just sort-and-count.
@sverre I provided a link to how to calculate the mode which doesn't allocate a count array and then provided an example for a quick and easy mode calculation which does. I can't imagine that allocating counts is going to be too much of a problem, if arr is 1,000,000 elements long, this is only 8 MB of memory. Your trick to use counts(minval:maxval) instead is nice however, and I updated my answer to include this.
@RethnarajRambabu No problem. You don't need to thank people with a comment however, just remember to up vote answers which are helpful and to accept an answer.
@Chris it doesn't matter if arr is 10 or 1,000,000 elements, if the first two elements are (/0, HUGE(i)/). What's important is the range, not the size.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.