如何使用awk从ID中获取具有各种观察/变量的信息。作为一个例子,我有两个ID(a,b)。两者都有不同年龄的6个观测值,并且测量值不同
根据ID和年龄对文件进行排序。 '行号'不是实际数据文件的一部分,但标题是!
我想使用awk识别并提取{print}"测量"每个唯一ID的最早年龄和最新年龄之间的差异。看下面的例子,对于ID(a),我想获得50-11 = 39。
id age measurement
1 a 2 11
2 a 4 20
3 a 6 19
4 a 7 89
5 a 8 43
6 a 12 50
7 b 1 15
8 b 3 23
9 b 5 30
10 b 6 33
11 b 7 45
12 b 10 60
如果您能详细解释我可以学习,我将非常感谢。
答案 0 :(得分:2)
鉴于行号不是数据的一部分而是标题,文件看起来更像:
id age measurement
a 2 11
a 4 20
a 6 19
a 7 89
a 8 43
a 12 50
b 1 15
b 3 23
b 5 30
b 6 33
b 7 45
b 10 60
此脚本根据需要分析该文件:
awk 'NR==1 { next }
$1 != id { if (id != "") print id, id_max - id_min; id = $1; id_min = $3; }
{ id_max = $3 }
END { if (id != "") print id, id_max - id_min; }' data
第一行会跳过文件的第一行。
第二行检查ID是否已更改;如果是,则检查是否存在旧ID,如果是,则打印数据。然后它存储当前ID并记录最小年龄的测量值。
第三行记录当前ID的当前最大年龄的度量。
如果文件中有任何数据,最后一行会打印出文件中最后一组的数据。
示例输出:
a 39
b 45
即使数据未按ID和年龄排序,代码也可以适应工作:
awk 'NR==1 { next }
{ if (group[$1]++ == 0)
{
order[++sequence] = $1
id_age_min[$1] = $2; id_val_min[$1] = $3
id_age_max[$1] = $2; id_val_max[$1] = $3
}
if ($2 < id_age_min[$1]) { id_age_min[$1] = $2; id_val_min[$1] = $3; }
if ($2 > id_age_max[$1]) { id_age_max[$1] = $2; id_val_max[$1] = $3; }
}
END { for (i = 1; i <= sequence; i++)
{
id = order[i];
print id, id_val_max[id] - id_val_min[id]
}
}' data
这会跳过标题行,然后在组到达时跟踪这些组,并安排按顺序打印数据(group
和order
- 和sequence
)。对于每一行,如果之前未见过该组,请设置当前行的数据(值均为最小值和最大值)。
如果当前行($2
)中的年龄小于当前最小年龄(id_min_age[$1]
)的年龄,请记录新年龄和相应的值。如果当前行中的年龄大于当前最大年龄(id_max_age[$1]
)的年龄,请记录新年龄和相应的值。
最后,对于序列中的每个ID,打印出ID以及该ID的最大值和最小值之间的差异。
随机数据:
id age measurement
a 12 50
b 10 60
a 4 20
b 3 23
b 5 30
a 7 89
b 6 33
b 7 45
a 8 43
a 6 19
a 2 11
b 1 15
示例输出:
a 39
b 45
恰好在a
行之前出现b
行,因此输出与以前相同。
更多数据(注意b
此时出现a
):
id age measurement
b 10 60
a 12 50
a 4 20
b 3 23
c 2 19
d -9 20
d 10 31
e 10 31
b 5 30
a 7 89
b 6 33
e -9 20
b 7 45
a 8 43
a 6 19
f -9 -3
f -7 -1
g -2 -8
g -8 -3
a 2 11
b 1 15
结果:
b 45
a 39
c 0
d 11
e 11
f 2
g -5