2

I have a tab-separated file looking like this:

A 1234
A 123245
A 4546
A 1234
B 24234
B 4545
C 1234
C 1234

Output: 
A 3
B 2
C 1

Basically I need counts of unique values that belong to the first column, all in one commando with pipelines. As you may see, there can be some duplicates like "A 1234". I had some ideas with awk or cut, but neither of the seem to work. They just print out all unique pairs, while I need count of unique values from the second column considering the value in the first one.

awk -F " "'{print $1}' file.tsv | uniq -c
cut -d' ' -f1,2 file.tsv | sort | uniq -ci

I'd really appreciate your help! Thank you in advance.

ta4le
  • 93
  • 1
  • 7
  • sort + uniq and then [this](https://stackoverflow.com/questions/27986425/using-awk-to-count-the-number-of-occurrences-of-a-word-in-a-column) – KamilCuk Jun 19 '20 at 09:45
  • 1
    Why are you using `cut -d' '` (i.e. telling `cut` to use a blank instead of a tab as the separator) when your file is tab-separated? – Ed Morton Jun 19 '20 at 12:18

5 Answers5

6

With complete awk solution could you please try following.

awk 'BEGIN{FS=OFS="\t"} !found[$0]++{val[$1]++} END{for(i in val){print i,val[i]}}' Input_file

Explanation: Adding detailed explanation for above.

awk '                  ##Starting awk program from here.
BEGIN{
  FS=OFS="\t"
}
!found[$0]++{       ##Checking condition if 1st and 2nd column is NOT present in found array then do following.
  val[$1]++            ##Creating val with 1st column inex and keep increasing its value here.
}
END{                   ##Starting END block of this progra from here.
  for(i in val){       ##Traversing through array val here.
    print i,val[i]     ##Printing i and value of val with index i here.
  }
}
'  Input_file          ##Mentioning Input_file name here.
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
2

Using GNU awk:

$ gawk -F\\t '{a[$1][$2]}END{for(i in a)print i,length(a[i])}' file

Output:

A 3
B 2
C 1

Explained:

 $ gawk -F\\t '{               # using GNU awk and tab as delimiter
    a[$1][$2]                  # hash to 2D array
 }
 END {                         
     for(i in a)               # for all values in first field
         print i,length(a[i])  # output value and the size of related array
 }' file
James Brown
  • 36,089
  • 7
  • 43
  • 59
2
$ sort -u file | cut -f1 | uniq -c
   3 A
   2 B
   1 C
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
2

Another way, using the handy GNU datamash utility:

$ datamash -g1 countunique 2 < input.txt
A   3
B   2
C   1

Requires the input file to be sorted on the first column, like your sample. If real file isn't, add -s to the options.

Shawn
  • 47,241
  • 3
  • 26
  • 60
1

You could try this:

cat file.tsv | sort | uniq | awk '{print $1}' | uniq -c | awk '{print $2 " " $1}'

It works for your example. (But I'm not sure if it works for other cases. Let me know if it doesn't work!)