文件1:
HOGBRM443983 -2522.00 19800826
HOGBRM445985 -2389.00 19801101
HOUSAM1891409 -1153.00 19811228
HOUSAM2004289 -650.00 19860101
HOUSAM2005991 -843.00 19860109
HOCANM388722 -1546.00 19860116
HOUSAM2007297 -1882.00 19860125
HOUSAM2007389 -1074.00 19860128
HOITAM801038516 -691.00 19860128
第 2 列和第 3 列分别包含第 1 列中每个 id 的值和出生日期信息(年、月、日)。我想检查每个出生年份中有多少个 id 以及不同年份的 id 的平均值(来自第二列)是多少。例如,在 file1 中,分别有 1980 年、1981 年和 1986 年的 2、1 和 6 个 id,因此输出应为:
output:
1980 2 -2455.5
1981 1 -1153.00
1986 6 -114.33
其中第一列显示出生年份,第二列显示每年内的多个id,第三列是不同年份的id的平均值。
考虑到真实数据确实巨大,任何建议将不胜感激。
答案1
cut -c1-35 infile | datamash -W -g 3 count 3 mean 2
请注意,您需要首先处理您的数据(我使用它cut
是因为它是您输入样本的明显选择,但任何工具都可以),以便从出生日期中删除月份和日期:
HOGBRM443983 -2522.00 1980
HOGBRM445985 -2389.00 1980
HOUSAM1891409 -1153.00 1981
HOUSAM2004289 -650.00 1986
......
然后才将其通过管道传输到datamash
.
这还假设第三列按年份排序(如果未排序,请使用datamash -s -W -g ...
)
答案2
awk 的答案:
awk '{y=substr($3,1,4); c[y]++; s[y]+=$2} END {for (y in c) {print y, c[y], (s[y]/c[y])}}' file.txt
答案3
考虑使用真实的数据库。
用一个在 Vagrant VM 中设置 Postgres 沙箱,我使用以下步骤执行此操作:
CREATE TABLE MyData (id text, val float, bday date);
INSERT INTO MyData VALUES
('HOGBRM443983',-2522.00,'1980-08-26'),
('HOGBRM445985',-2389.00,'1980-11-01'),
('HOUSAM1891409',-1153.00,'1981-12-28'),
('HOUSAM2004289',-650.00,'1986-01-01'),
('HOUSAM2005991',-843.00,'1986-01-09'),
('HOCANM388722',-1546.00,'1986-01-16'),
('HOUSAM2007297',-1882.00,'1986-01-25'),
('HOUSAM2007389',-1074.00,'1986-01-28'),
('HOITAM801038516',-691.00,'1986-01-28')
;
SELECT
extract(year FROM bday) AS yr,
count(id) AS count,
avg(val) AS average
FROM mydata GROUP BY yr;
输出是:
yr | count | average
------+-------+-------------------
1981 | 1 | -1153
1980 | 2 | -2455.5
1986 | 6 | -1114.33333333333
(3 rows)
您可能可以通过文本处理来处理这个问题,但是您提到数据很大,并且实际的数据库是设计的对于这种计算。 (我链接到的博客文章包含设置 Postgres 沙箱的所有步骤。)
答案4
磨坊主是为了解决以下问题而创建的:
$ cat hogbrm.txt | \
mlr --nidx --repifs put '$3=sub(string($3),"(....).*", "\1")' \
then stats1 -a count,mean -f 2 -g 3
1980 2 -2455.500000
1981 1 -1153.000000
1986 6 -1114.333333
语境:
- 使用
--nidx
因为没有标题,只有位置索引列 - 使用
--repifs
多个空格分隔列 - 用于
sub
删除日期的最后四位数字(第 3 列) - 用于
stats1
计算按第 3 列分组的第 2 列的计数和平均值