web-dev-qa-db-ja.com

スプレッドシートの2つの列に基づいて一意の値の数を数える

スプレッドシートの2つの列に基づいて一意の値の数をカウントする必要があります。

ファイルが次のようになり、名前、姓、会社の順になっていると仮定します。

joe allen ibm
joe smith ibm
joe allen google
joe smith google
rachel allen google

そして、姓を無視しながら、各会社の一意の名の数を数える必要があります。

joe ibm 2
joe google 2
rachel google 1

私はこのコードを持っています:

sort file.tsv | uniq -ci | awk '{print $2,$1}'

姓の列を削除するだけで、そのコードは機能します。しかし、その列を削除したくない場合は、awkにそれを無視させ、出力を新しいファイルに保存するだけですか?

データはタブで区切られています\t

3
Sveisa

2次元配列 を使用したGNU awkソリューション

gawk -F $'\t' '{a[$1][$3]++} END {for (i in a) for (j in a[i]) print i, j, a[i][j]}' foo.txt
  • a[$1][$3]++名と姓の各組み合わせに対して、カウントをインクリメントします
  • 次に、名と各名に関連付けられた会社名をループします。

古い形式の多次元配列を使用して他のawksを機能させる別の方法:

awk -F $'\t' '{a[$1, $3]++} END{for (i in a) {split (i, sep, SUBSEP); print sep[1], sep[2], a[i]}}' foo.txt
  • 古いメソッドは実際にSUBSEPで区切られたインデックスの連結を使用するため、元のインデックスを取得するにはSUBSEPで分割する必要があります。
2
muru

Counterモジュールのcollectionsクラスを使用するPythonicソリューションは、イテラブルの各要素の出現回数をカウントします。

#!/usr/bin/env python2
import collections
with open('file.txt') as f:
    names = []
    for line in f:
        names.append(line.strip().split()[0] + ' ' + line.strip().split()[2])
    result_dict = collections.Counter(names)
    for person in result_dict:
        print person + ' ' + str(result_dict[person])
3
heemayl

cutを使用して、最初に操作する列を選択できます。したがって、列はスペースで区切られ、FNAME SNAME COMPANYであるため、使用できる列1および3のみが必要です。

cut -d' ' -f1,3 file.tsv | sort | uniq -ci

これは、cutに、区切り文字として単一のスペース ''を使用して分離し、列1と3をソートに渡すように指示します。

次のような出力が生成されます。

 cut -d' ' -f1,3 file.tsv | sort | uniq -ci
      2 joe google
      2 joe ibm
      1 rachel google
2
AJefferiss

次のPerl onelinerは、データを抽出します。

Perl -e '/(.*)\t.*\t(.*)/ and $a{"$1 $2"}++ for (<>); print "$_ $a{$_}\n" foreach (keys%a);' file.tsv

出力:

joe ibm 2
joe google 2
rachel google 1
2
Sylvain Pineau