转置表

时间:2017-06-09 07:12:51

标签: python unix awk sed

我想转置一个如下所示的文件,其中第二列和每个列标题(B4,B3,E0)可以取两个值。我希望B4 B3 ...的所有值都在一行中。这意味着B4 B3 E0将是单独的行。

如何用例如awk sed或python。我可以在python中进行简单的转置,但我不明白如何解决这个特殊的问题。

输入:第2列和第3列具有相同的列名,即B4,类似第4和第5列具有相同的列名,即B3,依此类推。当我们转置两个对应于B4的值时,应该像{{{{{{{ 1}}。它应该在一条线上。输入文件包含20多列和2000行。

输入:

12 13 13 14 13 13 12 13 13 13 12 13

期望的输出:

ID  B4    B3    
 1  12  13  19  21  
 2  13  14  19  21  
 3  13  13  19  21  
 4  12  13  19  19  
 5  13  13  18  19  
 6  12  13  19  21

这就是我的尝试:

ID 1 1 2 2 3 3 4 4 5 5 6 6
B4 12  13 13  14 13  13 12  13 13  13 12  13
B3 19  21 19  21 19  21 19  19 18  19 19  21

还尝试了python -c "import sys; print('\n'.join(' '.join(c) for c in zip(*(l.split() for l in sys.stdin.readlines() if l.strip()))))" < input file>output file 代码,但没有运气。

2 个答案:

答案 0 :(得分:3)

awk 解决方案:

awk 'NR==1{ for (i=1; i<=NF; i++) col[i]=$i }
     NR>1{ 
         col[1]=sprintf("%s %s %s",col[1],$1,$1); j=1; 
         for (i=2; i<=NF; i+=2) {
             j++; col[j]=sprintf("%s %s %s",col[j],$i,$(i+1)) 
         }
     }
     END { len=length(col); for (i=1; i<=len; i++) print col[i] }' input

输出:

ID 1 1 2 2 3 3 4 4 5 5 6 6
B4 12 13 13 14 13 13 12 13 13 13 12 13
B3 19 21 19 21 19 21 19 19 18 19 19 21
  • NR==1{ for(i=1;i<=NF;i++) col[i]=$i } - 在第1行累积列名称

  • col[1]=sprintf("%s %s %s",col[1],$1,$1) - 连接第一个ID列的值

  • j++; col[j]=sprintf("%s %s %s",col[j],$i,$(i+1)) - 连接每个下一列的值(每列两个值)

答案 1 :(得分:1)

此python代码解决了您的问题

import sys

header = sys.stdin.readline().strip().split()
transposed = [[item] for item in header]

for line in sys.stdin.readlines():
    items = line.strip().split()
    transposed[0].append(items[0])
    for i in range(1, len(transposed)):
        transposed[i].extend(items[2*i - 1: 2*i + 1])

for line in transposed:
    print(" ".join(line))