【问题标题】:How to extract 45,000 columns from a space separated file with 500,000 columns according to a list of column name file using awk如何使用 awk 根据列名文件列表从包含 500,000 列的空格分隔文件中提取 45,000 列
【发布时间】:2022-12-05 23:50:35
【问题描述】:

a.txt 包含 500,000 列和 2000 行。下面的示例文件仅显示该文件中的前 9 列。该文件的第一行有标题。

chromosome SNPID rsid position alleleA alleleB 2409086 3514581 3635346 ...
1 1:55487346_C_G rs12117661 55487346 C G 1 0 0 ...
1 1:55487648_A_G rs11588151 55487648 A G 1 0 0 ...
1 1:55489542_C_T rs34232196 55489542 C T 1 0 0 ...
1 1:55490861_T_C rs4500361 55490861 T C 1 0 0 ...
1 1:55491702_T_C rs4927191 55491702 T C 0.894118 0 0 ...
1 1:55491780_A_G rs200159426 55491780 A G 0.894118 0 0 ...
...

b.txt 包含 45000 列,显示每一行的列名。我想根据b.txt从a.txt中提取列。

chromosome
SNPID
rsid
position
alleleA
alleleB
2409086
3635346
...

c.txt 是我的预期结果。 c.txt 应该是一个空格分隔的表,有 45000 列和 2000 行。

chromosome SNPID rsid position alleleA alleleB 2409086 3635346 ...
1 1:55487346_C_G rs12117661 55487346 C G 1 0 ...
1 1:55487648_A_G rs11588151 55487648 A G 1 0 ...
1 1:55489542_C_T rs34232196 55489542 C T 1 0 ...
1 1:55490861_T_C rs4500361 55490861 T C 1 0 ...
1 1:55491702_T_C rs4927191 55491702 T C 0.894118 0 ...
1 1:55491780_A_G rs200159426 55491780 A G 0.894118 0 ...
...

我尝试使用cut 来解决这个问题,但它显示参数列表太长(因为我需要提取 45000 列)。我知道 awk 可以解决这个问题,但我不熟悉 awk,也没有找到任何答案。有没有人有解决方案?

cut -f 1,$(
    head -n1 a.txt |
    tr ' ' '\n' |
    grep -nf b.txt |
    sed ':a;$!N;s/:[^\n]*\n/,/;ta;s/:.*//'
) a.txt > c.txt
-bash: /usr/bin/cut: Argument list too long

【问题讨论】:

  • 我不会对这么多列使用 cut。相反,试试 pandas(一个用于表格数据的 Python 库)。或者使用 Perl。
  • 你关心b.txt中指定的顺序吗?

标签: bash awk cut


【解决方案1】:

假设这是filter.awk

NR == FNR { # reading the first file
    for (i=1; i<=NF; i++)
        wanted[$i] = i
    next
}

FNR == 1 {
    for (i=1; i<=NF; i++)
        header[i] = $i
}

{
    for (i=1; i<=NF; i++)
        if (header[i] in wanted)
            printf "%s ", $i
    print ""
}

然后,给你的样本 a.txt 和

$ cat b.txt
chromosome
rsid
2409086

我们得到

$ awk -f filter.awk b.txt a.txt
chromosome rsid 2409086
1 rs12117661 1
1 rs11588151 1
1 rs34232196 1
1 rs4500361 1
1 rs4927191 0.894118
1 rs200159426 0.894118

【讨论】:

  • 你不能把for (i=1; i&lt;=NF; i++)换成b.txt吗?它每行包含一个列名,因此不必遍历这一行中的单词,对吧?
猜你喜欢
  • 1970-01-01
  • 2011-12-13
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
相关资源
最近更新 更多