【问题标题】:Merging similar columns from different files into a matrix将来自不同文件的相似列合并到一个矩阵中
【发布时间】:2016-01-19 15:18:36
【问题描述】:

我有以下格式的文件,每个文件的第一列在所有文件中都是通用的:

  File1.txt
  ID    Score            
  ABCD   0.9
  BCBS   0.2
  NBNC   0.67
  TCGS   0.8

  File2.txt
  ID    Score            
  ABCD   0.3
  BCBS   0.9
  NBNC   0.73
  TCGS   0.12

  File3.txt
  ID    Score            
  ABCD   0.23
  BCBS   0.65
  NBNC   0.94
  TCGS   0.56

我想将所有文件的第二列(分数列)与第一列合并,并显示文件名减去每个文件的扩展名作为标题,以识别分数来自哪里矩阵看起来像

   ID     File1  File2 File3
  ABCD     0.9   0.3   0.23
  BCBS     0.2   0.9   0.65        
  NBNC     0.67  0.73  0.94          
  TCGS     0.8   0.12  0.56         

【问题讨论】:

  • 那么,您尝试了哪些方法,您在哪里遇到了问题?每个文件中的行是否保证顺序相同,因此无需计算出哪个分数属于哪个ID?您是否尝试过仅使用 10 个文件? 360k 列意味着每行长度将超过 1 MiB;这可能会给程序带来压力。
  • 嗨@JonathanLeffler 我试图为所有文件建立一个过去的命令并将其通过管道传递给awk,但我知道对于这么多文件来说这将是一种可悲的方式,是的顺序完全一样!
  • 编辑您的问题以显示 3 个 small(例如,每 3 或 4 行乘 3 或 4 列)输入文件和给定输入的预期输出。得到答案后,您可以自己将其从 3 个文件扩展到 194 个文件和 3 或 4 个到 364893 列。
  • 请注意,问题的原始版本开始于“我有 194 个文件,格式如下,每个文件有 364893 列,第一列在所有文件中是通用的”。这引发了我对修订版显然没有的兆字节行长度的观察。

标签: shell matrix awk multiple-columns


【解决方案1】:
$ cat tst.awk
BEGIN { OFS="\t" }
FNR>1 { id[FNR] = $1; score[FNR,ARGIND] = $2 }
END {
    printf "%s%s", "ID", OFS
    for (colNr=1; colNr<=ARGIND; colNr++) {
        sub(/\..*/,"",ARGV[colNr])
        printf "%s%s", ARGV[colNr], (colNr<ARGIND?OFS:ORS)
    }
    for (rowNr=2; rowNr<=FNR; rowNr++) {
        printf "%s%s", id[rowNr], OFS
        for (colNr=1; colNr<=ARGIND; colNr++) {
            printf "%s%s", score[rowNr,colNr], (colNr<ARGIND?OFS:ORS)
        }
    }
}

$ awk -f tst.awk File1.txt File2.txt File3.txt
ID      File1   File2   File3
ABCD    0.9     0.3     0.23
BCBS    0.2     0.9     0.65
NBNC    0.67    0.73    0.94
TCGS    0.8     0.12    0.56

选择一些不能在你的输入中出现的字符串作为OFS,我使用了tab。

如果您没有 GNU awk,请在脚本开头添加 FNR==1{ ARGIND++ }

【讨论】:

  • Ed,我有 194 个这样的文件,它们不完全命名为 file1 , file2 等等,我试图在 194 个文件上使用与 awk -f merge.awk *_max.txt 相同的代码假设它会拾取具有相同扩展名的文件并将它们合并在一起,但是由于该过程太长而被杀死,您有什么建议吗? TIA
【解决方案2】:

另一种选择

$ awk 'NR==1{$0=$1"\t"FILENAME}1' File1 > all; 
  for f in File{2..6}; 
     do 
       paste all <(p $f) > temp && cp temp all; 
     done

定义函数p为

p() { awk 'NR==1{print FILENAME;next} {print $2}' $1; }

我将您的数据复制到 6 个相同的文件 File1..File6 并且脚本生成了这个。大部分工作是设置列名

ID      File1   File2   File3   File4   File5   File6
  ABCD   0.9    0.9     0.9     0.9     0.9     0.9
  BCBS   0.2    0.2     0.2     0.2     0.2     0.2
  NBNC   0.67   0.67    0.67    0.67    0.67    0.67
  TCGS   0.8    0.8     0.8     0.8     0.8     0.8

【讨论】:

    猜你喜欢
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2018-06-06
    • 1970-01-01
    • 2011-12-25
    • 2015-06-04
    • 1970-01-01
    相关资源
    最近更新 更多