csvkit

csvkit

次のようにタブ区切りのファイルがあるとしますdata.tsv

1 a 3
2 b 2
3 a 10
2 c 2
2 a 8

次のコマンドを使用して、列1の値をIDから名前に変換したいと思いますmap.tsv

1 foo
2 bar
3 baz

結果は次のとおりです。

foo a 3
bar b 2
baz a 10
bar c 2
bar a 8

私は知っている一ついくつかのAWKトリックを使用してマッピングを実行することは可能ですが、複数の列に複数のマッピングを使用し、次のように簡単な呼び出しを行うことができることを願っています。

$ my_map_command 1:map.tsv < data.tsv

同様の操作を実行するコマンドはありますか?

答え1

csvkit

csvjoinパッケージのコマンドcsvkit同様の動作を達成するために使用できます。

$ csvjoin -tH -c 1,1 data.tsv map.tsv 2> /dev/null
a,b,c,b2
1,a,3,foo
2,b,2,bar
3,a,10,baz
2,c,2,bar
2,a,8,bar

csvcut列の並べ替えと削除は簡単で、同じパッケージで実行できます。

コアツール

この基準を使用することもできjoin(1)ますが、データを並べ替える必要があります(ソートされていない場合は地図も含めて)。

$ join -j1 -t '       ' <(sort -k1 data.tsv) map.tsv
1       a       3       foo
2       a       8       bar
2       b       2       bar
2       c       2       bar
3       a       10      baz

どちらの場合も、一度に1つのマッピングしか実行できないため、追加の呼び出しのために複数のマッピングをパイプで接続する必要があります。

答え2

次のファイルに入れてくださいmy_map_command

#!/usr/bin/awk -f
FNR==NR{map[$1]=$2}
FNR!=NR{
    printf "%s%s",map[$1],OFS
    for (i=2; i<=NF; i++) printf "%s%s",$i,OFS
    printf "\n"
}

次に、次を実行します。

chmod u+x my_map_command

次のようにスクリプトを呼び出します。

./my_map_command map.tsv data.tsv

複数のマップファイル:

./my_map_command <(cat map1.tsv map2.tsv) data.tsv

答え3

ファイルパラメータ間に変数を割り当てます。

awk '!data{map[$1]=$2; next} $1 in map{$1=map[$1]} 1' map1 map2... data=1 data
  • mapフラグが与えられるまで値を配列として読み込みます。
  • フラグ値(data=1パラメーター)を指定した後、データのフィールドをマップされた値と交換します。

awk '
!data {
    map[field,$1]=$2
    maps[field]
    next
}
{
    for (i in maps)
        if ((i,$i) in map)
            $i=map[i,$i]
}
1' field=1 map1 field=2 map2 data=1 data
  • data値のマップのフィールド1map1
  • data値のマップのフィールド2map2

答え4

または、既に知っている言語を使用して表形式のデータを照会することもできます。;

構文は簡単です。q "<SQL Query>"または、q -t "…"ファイルがtsvまたは-d …別の区切り文字の場合。あなたのクエリは次のとおりです。

SELECT m.c2, d.c2, d.c3 
FROM data.tsv AS d INNER JOIN map.tsv AS m
                   ON d.c1==m.c1

q - text as data包装 どこでも)は適用できるきれいなツールです。SQLすべての表形式の区切りデータ。 STDINも動作します。ファイル名に「-」を指定し、JOIN - as mmap.tsvを入力したものに置き換えることをお勧めします。

良い「ボーナス」q:SQLを使用して計算を実行することもできますORDERGROUPすべて表示:

q 'SELECT m.c2 AS I, d.c2, d.c3, ROUND(d.c3*0.4, 2) as b
   FROM data.tsv AS d INNER JOIN - AS m
                      ON d.c1==m.c1
   ORDER BY I' < map.tsv

bar b 2 0.8
bar c 2 0.8

注:「q」という名前は検索できません。検索するときは、「text-as-data」または「harelba」(作成者)を追加してください。

関連情報