根据列将数据分组到类别中

时间:2018-01-14 18:20:06

标签: bash text awk

我有一个制表符分隔文件,其中包含2列:

new.txt
    1.01   yes
    2.00   no
    0.93   no
    1.2223 yes
    1.7211 no

我想修改它的内容,好像有两个类别:

new_categorized.txt
yes    no
1.01   2.00
1.2223 0.93
       1.7211

我在R(here)中找到了一个类似的答案,但是我需要用bash或awk来做。 我很感激你的帮助。

3 个答案:

答案 0 :(得分:3)

$ cat tst.awk
BEGIN { FS=OFS="\t" }
!($2 in label2colNr) {
    label2colNr[$2] = ++numCols
    colNr2label[numCols] = $2
}
{
    colNr = label2colNr[$2]
    val[++numRows[colNr],colNr] = $1
    maxRows = (numRows[colNr] > maxRows ? numRows[colNr] : maxRows)
}
END {
    for (colNr=1; colNr <= numCols; colNr++) {
        printf "%s%s", colNr2label[colNr], (colNr<numCols ? OFS : ORS)
    }

    for (rowNr=1; rowNr <= maxRows; rowNr++) {
        for (colNr=1; colNr <= numCols; colNr++) {
            printf "%s%s", val[rowNr,colNr], (colNr<numCols ? OFS : ORS)
        }
    }
}

$ awk -f tst.awk file
yes     no
1.01    2.00
1.2223  0.93
        1.7211

以上内容适用于任何UNIX系统上任何shell中的任何awk,无论您在第二个字段中有多少类别,无论它们的值是什么。

答案 1 :(得分:2)

使用bash,GNU grep和paste:

echo -e "yes\tno"
paste <(grep -Po '^\t\K.*(?=\tyes)' new.txt) <(grep -Po '^\t\K.*(?=\tno)' new.txt)

输出:

yes     no
1.01    2.00
1.2223  0.93
        1.7211

答案 2 :(得分:2)

GNU awk 解决方案:

awk '{ a[$2][($2=="yes"? ++y : ++n)]=$1 }
     END{ 
         max=(y > n? y:n); 
         print "yes","no";
         for(i=1; i<=max; i++) print a["yes"][i], a["no"][i] 
     }' OFS='\t' file | column -tn

输出:

yes     no
1.01    2.00
1.2223  0.93
        1.7211