web-dev-qa-db-ja.com

awkは列のサブセットに基づいて一意の行を決定します

指定した列のサブセットに対して一意のcsvの行を返すことを探しています。

サンプルデータ:

Col1,Col2,Col3,Col4
A,10,50,2017
A,10,05,2017
B,20,30,2017
B,20,03,2017
C,30,100,2017
C,30,111,2017
C,30,100,2016
C,40,111,2016
C,30,123,2015

このコマンドは、単一の列(この場合は列1)の一意の値を出力します。

awk -F , '{ a[$1]++ } END { for (b in a) { print b } }' file

返却値

Col1
A
B
C

これを2列またはn列で実行するコマンドが必要です。

2列(Col1およびCol3)を使用する一意の行に必要な出力:

Col1,Col3
A,50
A,05
B,30
B,03
C,100
C,111
C,123

Col1およびCol4の場合

Col1,Col4
A,2017
B,2017
C,2017
C,2016
C,2015

3列のCol1、Col2、およびCol3の場合

Col1,Col2,Col3
A,10,50
A,10,05
B,20,30
B,20,03
C,30,100
C,30,111
C,40,111
C,30,123
3
conor

特定の列を印刷するには、列1と列4を実行します。

awk -F',' '{print $1, $4}' file

ここでのコマンドは、awkに '、'で区切られた指定された列を印刷するように要求することです。

列番号を変更したり、$ NUMを追加/削除して別の列を取得したりできます。

sortと組み合わせて、一意の行を取得します。

awk -F',' '{print $1, $4}' file | sort -u

-uフラグは、重複したアイテムを出力から削除します。

1
P.-H. Lin

これを行うには、ハッシュキーの列値を組み合わせます。入力がソートされていると仮定すると、このワンパスソリューションは列1-3で機能します。

awk '!h[$1,$2,$3]++ { NF--; print }' FS=, OFS=, data.csv

出力:

Col1,Col2,Col3
A,10,50
A,10,05
B,20,30
B,20,03
C,30,100
C,30,111
C,40,111
C,30,123

列1および4については、次のようにします。

awk '!h[$1,$4]++ { print $1, $4 }' FS=, OFS=, data.csv

出力:

Col1,Col4
A,2017
B,2017
C,2017
C,2016
C,2015
2
Thor

Python

#!/usr/bin/env python

import sys

filename = sys.argv[1]
col_nums = sys.argv[2:]
if not col_nums:
    sys.exit()

rows_unique = []
for row in open(filename).read().splitlines():
    cells = row.split(',')
    # Select cells in row based on given column numbers.
    cells_selected = [cells[int(col_num)] for col_num in col_nums]
    row_selected = ','.join(cells_selected)
    if row_selected not in rows_unique:
        print(row_selected)
        rows_unique += [ row_selected ]

実行可能スクリプトとして保存してから呼び出します(列のインデックスはゼロであることに注意してください):

$ get_unique_rows_per_column.py file 0 2
Col1,Col3
A,50
A,05
B,30
B,03
C,100
C,111
C,123
0
wjandrea