将基于列的TSV合并为多行

时间:2015-03-02 23:49:46

标签: python-2.7 csv awk tsv data-cleaning

我有两个TSV文件,我想根据第一列中的通用性合并它们。该列没有标题,但数据是每个公司的名称。

我有一个接近我想要的awk代码。问题是我想在每次提到公司时合并信息,而不仅仅是第一次。

items.tsv看起来像这样:

IBM 0.0107  100.0%
APPL    0.0457  98.0%
GOOGL   0.0227  100.0%
GOOGL   0.0197  100.0%
GOOGL   0.0997  90.0%
GOOGL   0.0397  10.0%

vendors.tsv:

IBM Dec 2011
APPL Jan 2014
GOOGL June 2015 

使用我的代码,输出是:

IBM 0.0107  100.0% Dec 2011
APPL 0.0457 98.0% Jan 2014
GOOGL 0.0227    100.0% June 2015

缺少三条线!所需的输出是:

IBM 0.0107  100.0% Dec 2011
APPL 0.0457 98.0% Jan 2014
GOOGL 0.0227    100.0% June 2015
GOOGL   0.0197  100.0% June 2015
GOOGL   0.0997  90.0% June 2015
GOOGL   0.0397  10.0% June 2015

这是我一直在使用的代码:

awk '
    BEGIN {FS=OFS="\t"}
    NR==FNR {a[$1] = $2 FS $3; next}
    $1 in a {print $1, a[$1], $2, $3}
' items.tsv vendors.tsv

行的顺序无关紧要。数据由制表符\ t分隔。我希望有人可以提供帮助!

(注意,awk代码与我一直使用的相同,输出是由我输入的,所以\ t是一些常规空间等等。)

1 个答案:

答案 0 :(得分:1)

问题只是输入文件的顺序。使用NR == FNR惯用法(通常)将第一个文件读入数组,然后为第二个文件中的每个记录输出一行,使用该数组与第一个文件中的信息“连接”。由于您将供应商文件作为第二个文件,因此读入了三个记录并写出了三行。

同样重要的是,第一个文件具有用作数组索引的唯一键。只能有一个a["GOOGL"],但是再次通过切换输入文件的顺序,这个问题也会消失。

$ cat vendors.tsv 
IBM Dec 2011
APPL    Jan 2014
GOOGL   June    2015

$ cat item.tsv
IBM 0.0107  100.0%
APPL    0.0457  98.0%
GOOGL   0.0227  100.0%
GOOGL   0.0197  100.0%
GOOGL   0.0997  90.0%
GOOGL   0.0397  10.0%

$ cat merge.awk
BEGIN {FS=OFS="\t"}
NR==FNR {a[$1] = $2 FS $3; next}
$1 in a { print $1, $2, $3, a[$1] }

$ awk -f merge.awk vendors.tsv item.tsv
IBM 0.0107  100.0%  Dec 2011
APPL    0.0457  98.0%   Jan 2014
GOOGL   0.0227  100.0%  June    2015
GOOGL   0.0197  100.0%  June    2015
GOOGL   0.0997  90.0%   June    2015
GOOGL   0.0397  10.0%   June    2015