2015-10-05 68 views
1

我想根据另一列的值将列转置为若干较小的部分,例如,基于另一列的值将一列转置为行

1 ID1 V1 
2 ID1 V2 
3 ID1 V3 
4 ID2 V4 
5 ID2 V5 
6 ID3 V6 
7 ID3 V7 
8 ID3 V8 
9 ID3 V9 

我希望有所有V值为每个ID是在一行中例如

ID1 V1 V2 V3 
ID2 V4 V5 
ID3 V6 V7 V8 V9 

每个id具有不同的转置行数,如示例中所示。如果使用序列号列更容易执行此操作,那么也可以。

任何人都可以帮忙吗?

回答

1

下面是一个简单的awk的一行这样的伎俩:

awk '1 {if (a[$2]) {a[$2] = a[$2]" "$3} else {a[$2] = $3}} END {for (i in a) { print i,a[i]}}' file.txt 

输出:

ID1 V1 V2 V3 
ID2 V4 V5 
ID3 V6 V7 V8 V9 
+0

谢谢@pcantalupo,这是超级简单,但伟大的!有没有办法使用另一个“密钥”文件转置此文件?密钥文件有三列提供关于该文件的信息,即:“ID号”,“起始行”和“结束行”。例如密钥文件的前三行如下所示:ID1 1 3 ID2 4 5 ID3 6 9等等。 – Schuman

+0

要么更新此问题,要么将其作为另一个问题发布 – pcantalupo

0

如果您喜欢在JavaScript编码,这是如何使用的JLine做它的命令行:https://github.com/bitdivine/jline/

[email protected]:~$ cat ,,, | jline-foreach 'begin::global.all={}' line::'fields=record.split(/ +/);if(fields.length==3)tm.incrementPath(all,fields.slice(1))' end::'tm.find(all,{maxdepth:1},function(path,val){console.log(path[0],Object.keys(val).join(","));})' ID1 V1,V2,V3 ID2 V4,V5 ID3 V6,V7,V8,V9

该输入是: [email protected]:~$ cat ,,, 1 ID1 V1 2 ID1 V2 3 ID1 V3 4 ID2 V4 5 ID2 V5 6 ID3 V6 7 ID3 V7 8 ID3 V8 9 ID3 V9 [email protected]:~$

说明:这将构建一个树第一级分支是用户ID,第二级是V(版本?)。你可以为任何级别做到这一点。叶子只是柜台。首先,我们创建一个空的树:

'begin::global.all={}'

然后就是进来被分为计数器,ID和版本号的每一行。计数器被切掉只留下数组[用户ID,版本]。 incrementCounter创建树,有点像mkdir -p这些分支,虽然你实际上并不需要知道如何往往是每个用户,版本组合已经看到增加的叶计数器:

line::'fields=record.split(/ +/);if(fields.length==3)tm.incrementPath(all,fields.slice(1))' end::'tm.find(all,{maxdepth:1},function(path,val){console.log(path[0],Object.keys(val).join(","));})'

在结束我们有tm.find其行为就像UNIX查找并打印树中的每个路径。除了我们将搜索的深度限制到期望的分解点(1,但是如果你像我一样,接下来你会想要分解2,3,5或8个变量)。通过这种方式,您可以分解出故障点和值的列表,并且可以打印答案。

如果你永远不需要更深入的分解,你可能会想要坚持使用awk,因为它可能是预先安装的。