MODE function in awk

Hello,

Can someone pls help me with some statistical calculation in awk

In excel there is a statistical function called "Mode".

How Mode works:

MODE returns the most frequently occurring, or repetitive, value in array or range.

Eg if we have 5 numbers in 5 different columns ( 32,45,56,32,32)
The MODE(32,45,56,32,32) = 32

If we had (32,45,56,30,92) , then the MODE would return "#N/A"

How can I Code the "Mode" function in awk?

I tried this code below, but it didn't work.

thanks

 
#!/bin/sh
find . -name '*.txt' | while read line
do
gawk -F '\t' '$2== "A" {print $1"\t" $3"\t" Mode($7,$8,$9,$10)"\t" }' $line
done >out.txt

#!/bin/sh
find . -name "*.txt" | while read line
do
gawk -F '\t' '$2== "A" {print $1"\t" $3"\t" Mode($7,$8,$9,$10)"\t" }' $line
done >out.txt

You may try something like this:
(use should use nawk or /usr/xpg4/bin/awk on Solaris)

func mode(list, sep,  n, a, i, h, m, v) {
  sep = sep ? sep : FS
  n = split(list, a, sep)
  while (++i <= n) {
    if (++h[a] > m) {
      m = h[a]
      v = a
    }
  }
  return m > 1 ? v : "#N/A"
}

For example:

% cat file
32,45,56,32,32
32,45,56,30,92

% awk -F, '{ print mode($0) }
func mode(list, sep,  n, a, i, h, m, v) {
  sep = sep ? sep : FS
  n = split(list, a, sep)
  while (++i<= n) {
    if (++h[a] > m) {
      m = h[a]
      v = a
    }
  }
  return m > 1 ? v : "#N/A"
}' file
32
#N/A

What should the function return for an input like the one below?

1,1,2,2

radulov - it is bimodal, really. It should return a set: (1,2). I don't know what Excel does, just what statistics does. Mode is often used for data like 'birthdays of people in the room' or 'last names of people in a town' - data unlike numbers or numeric data with no real inherent meaning, just magnitude. Football (soccer) scores qualify in that category.

Another way...

awk -F\, '{
   for (i=1; i<=NF; ++i)
       if (max <= ++x[$i])
          max = x[$i]
} END {
   for (i in x)
       if (x == max)
          print i
}' file

shamrock's code is a lot closer to what's needed, except the (#/N/A) non-modal part.

As I am not very statistically inclined could you explain what non-modal means?

Thanks a lot guys,.

Sorry I am new in this area :confused:,i need some more help ...

How can incorporate yours codes in this code below?:confused:

 
#!/bin/sh
find . -name '*.txt' | while read line
do
gawk -F '\t' '$2== "A" {print $1"\t" $3"\t" Mode($7,$8,$9,$10)"\t" }' $line
done >out.txt

thanks

Thanks Jim,
I was not sure if it was supposed to return N/A or a set.
If I'm not missing something again:

% cat file
32,45,56,32,32
32,45,56,30,92
1,1,2,2
% awk -F, '{ print mode($0) }
func mode(list, sep,  n, a, i, h, m, k, f, r) {
  sep = sep ? sep : FS
  n = split(list, a, sep)
  while (++i <= n) if (++h[a] > m) m = h[a]
  for (k in a) m == h[a[k]] && f[a[k]]
  if (m > 1) for (k in f) r = r ? r sep k : k
  return r ? r : "#N/A"
  }' file
32
#N/A
1,2

Some awk interpreters (eg. mawk) do not support the abbreviated form func (you should use function instead).

Could you post a sample from your input file (*.txt => $line) and an example of the desired output?

hi guys,

i have N txt files , which looks like this:
I
nput file:

Wanted output:

Is there a MODE function in awk or Perl ?
So i can call in my script below.
This code below didnt work.

 
#!/bin/sh
find . -name '*.txt' | while read line
do
gawk -F '\t' '$2== "A" {print $1"\t" $3"\t" Mode($7,$8,$9,$10)"\t" }' $line
done >out.txt

thanks

Try this:
(use nawk or /usr/xpg4/bin/awk on Solaris)

awk>out.txt 'FNR == 1 || $0 = $0 FS mode($0) 
func mode(list, sep,  n, a, i, h, m, k, f, r) {
  sep = sep ? sep : FS
  n = split(list, a, sep)
  while (++i <= n) if (++h[a] > m) m = h[a]
  for (k in a) m == h[a[k]] && f[a[k]]
  if (m > 1) for (k in f) r = r ? r sep k : k
  return r ? r : "#N/A"
  }' file1 file2 ... filen