如何转置多个txt文件?

如何转置多个txt文件?

我有 1775 个 .txt 文件,每个 .txt 文件有 3023 行,它们看起来像这样:

RIBBY_g_5ZCV995_BI_SNP_D04_38774.CEL
FQC-10090295         0.007813
FQC-10119363         0.023438
FQC-10132112         0.093750
...
UNTIL_g_3ECO791_BI_SNP_H10_36454.CEL
FQC-10090295 0.187500
FQC-10119363 0.023438
FQC-10132112 0.039063
...

如何制作一个矩阵来表示转置这些 txt 文件,使它们看起来像这样:

                                     FQC-10090295 FQC-10119363 FQC-10132112  ...
RIBBY_g_5ZCV995_BI_SNP_D04_38774.CEL 0.007813     0.023438     0.093750  ...
UNTIL_g_3ECO791_BI_SNP_H10_36454.CEL 0.187500     0.023438     0.039063  ...

答案1

您的问题包含许多未指定的参数,但作为起点,请考虑以下bash脚本:

header=

for f in *.CEL
do
    if [ -z "$header" ]
    then
        l=${#f}                 # length of filename ...
        fmt="%-${l}s"           # ... determines width of first column

        header="$(printf "$fmt" "")"    # first column of first row is blank

        for col in $(awk '{print $1}' $f)
        do
            l=${#col}               # width of column
            [ $l -lt 8 ] && l=8     # min width of 8
            header="$header $(printf "%-${l}s" "$col")"     # append column label to header
            fmt="$fmt %-$l.6f"
        done
        printf '%s\n' "$header"         # header is first row of output
    fi

    printf "$fmt\n" "$f" $(awk '{print $2}' $f)     # print filename and all column 2 values
done

运行脚本给出:

                                     FQC-10090295 FQC-10119363 FQC-10132112
RIBBY_g_5ZCV995_BI_SNP_D04_38774.CEL 0.007813     0.023438     0.093750    

我将您的输入文件复制到第二个文件名,然后重新运行:

                                     FQC-10090295 FQC-10119363 FQC-10132112
RIBBY_g_5ZCV995_BI_SNP_D04_38774.CEL 0.007813     0.023438     0.093750    
RIBBY_g_5ZCV995_BI_SNP_D04_38775.CEL 0.007813     0.023438     0.093750    

该脚本首先循环遍历所有*.CEL文件。

对于第一个文件,脚本header基于所有文件名长度相同的假设构建标题行。在构建标题行时,该脚本还会构建一个用于显示柱状数据的printf格式字符串。fmt格式字符串中的第一个字段是长度足以显示文件名的字符串。

接下来,脚本循环遍历第一个输入文件中的所有“第 1 列”值,这些值是值标签。对于每一列,脚本再次获取值标签的长度(但不少于 8),并将该标签添加到标题中。它还向字符串添加浮点格式规范fmt

脚本循环遍历所有列标签后,它会输出已构造的标题字符串。

上述所有步骤都发生在第一的仅文件。

处理第一个文件的最后一步,以及仅有的处理第一个文件之后的所有文件的步骤是使用在第一次循环迭代期间创建的字符串printf来显示文件名和“第 2 列”值。fmt然后,脚本继续处理下一个*.CEL文件(如果有)。

此方法假设所有文件中的列标签相同,并且所有*.CEL文件名的长度相同。

答案2

您需要这样的东西:

$ cat tst.awk
BEGIN { OFS="\t" }
FNR==1 {
    row = $1
    rows[row]
    next
}
{
    col = $1
    cols[col]
    vals[row,col] = $2
}
END {
    printf "%s", ""
    for (col in cols) {
        printf "%s%s", OFS, col
    }
    print ""
    for (row in rows) {
        printf "%s", row
        for (col in cols) {
            printf "%s%s", OFS, vals[row,col]
        }
        print ""
    }
}

但没有输入/输出来澄清您的要求,我们可以对其进行测试(请参阅我的评论),这只是未经检验的猜测。

相关内容