다른 열의 정보를 고려하여 한 열의 값 평균을 계산하는 방법은 무엇입니까?

다른 열의 정보를 고려하여 한 열의 값 평균을 계산하는 방법은 무엇입니까?

파일 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년에 대한 ID가 각각 2개, 1개, 6개 있으므로 출력은 다음과 같습니다.

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날짜의 마지막 4자리(3열)를 제거하는 데 사용됩니다 .
  • stats13열로 그룹화된 2열의 개수와 평균을 계산하는 데 사용됩니다 .

관련 정보