我需要快速处理一个有很多冗余的文本文件。 我可以使用python,但我认为最简单,最快的将是在unix shell中使用awk,sed或perl。
数据有3列,我需要按(唯一)第1列和第3列分组,然后获取第2列的最后一个值
1,2,3
a 1 A
a 2 A
a 3 A
b 2 C
b 3 C
b 3 D
c 1 C
c 1 D
c 2 D
结果应该是:
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
答案 0 :(得分:1)
考虑到您的Input_file与显示的示例相同,并且在第一个和第三个字段的排序方法中,以下可能会帮助您。
awk '
FNR==1{
print;
next
}
!a[$1,$3]++{
if(a[prev]){
print prev,a[prev]};
a[$1,$3]=$2
}
{
prev=$1 FS $3
}
END{
if(a[prev] && prev){
print prev,a[prev]
}}
' SUBSEP=" " Input_file
输出如下:
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
答案 1 :(得分:1)
您可以使用此awk
:
awk '{key=$1 FS $3} !(key in arr){a[++n]=key} {arr[key]=$2}
END{for (i=1; i<=n; i++) print a[i], arr[a[i]]}' file
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
答案 2 :(得分:1)
此类任务有一个特殊工具 - datamash
:
datamash -W -t' ' --header-in -g 1,3 last 2 < input.txt
标头1,2,3
被丢弃以简化演示代码,因为它有另一个字段分隔符,而不是其他行,这使得任务复杂化。
<强>解释强>
-W, --whitespace
- 使用空格(一个或多个空格和/或制表符)作为字段分隔符。
-t, --field-separator=X
- 使用X代替TAB作为字段分隔符。
--header-in
- 第一个输入行是列标题(在我们的例子中,我们这样做只是为了省略标题)。-g, --group=X[,Y,Z]
- 通过字段X,[Y,Z]
分组。last
- 该组的最后一个值。<强>输出强>
a A 3
b C 3
b D 3
c C 1
c D 2
cat <(head -n 1 input.txt) <(tail -n +2 input.txt | datamash -W -t' ' -g 1,3 last 2)
<强>输出强>
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
答案 3 :(得分:0)
使用tac
和GNU sort
。
$ tac Group_Data | sort -u -k1,1 -k3 | awk '{if (NR == 1) print $0; else print $1,$3,$2}'
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
IMO python词典和强大的sorted功能使得python像其他任何类似的解决方案一样快速和有竞争力,特别是如果您将使用python进一步处理下游数据。在项目下面将它们用作Python字典的键,然后按第一和第二元素排序。
>>> groupdict = {}
>>> with open("Group_Data") as fp:
... for ii, lines in enumerate(fp):
... if ii == 0:
... header = lines.rstrip()
... else:
... fields = lines.split()
... groupdict[(fields[0],fields[2])] = fields[1]
...
>>> groupdict
{('b', 'C'): '3', ('a', 'A'): '3', ('c', 'D'): '2', ('c', 'C'): '1', ('b', 'D'): '3'}
>>> for ii,elem in enumerate(sorted(groupdict.items(), key = lambda x : (x[0],x[1]))):
... if ii == 0:
... print header
... key, value = elem
... print key[0],key[1],value
...
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2