如何通过考虑另一列的信息来计算一列中值的平均值?

如何通过考虑另一列的信息来计算一列中值的平均值?

文件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

gnu datamash

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 列的计数和平均值

相关内容