데이터 분석 작업을 하다 보면 숫자 배열을 분기(quarter) 또는 연도(year) 단위로 묶은 뒤 각 그룹의 평균이나 합계를 구해야 하는 경우가 자주 있습니다. 이번 글에서는 JavaScript를 활용해 하나의 배열을 분기별·연간 그룹으로 나누고, 각 그룹의 평균값을 손쉽게 계산하는 방법을 알아보겠습니다.
문제 상황
다음과 같은 숫자 배열이 있다고 가정해 보겠습니다.
const arr = [1,2,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
여기서 요구되는 것은 이 배열을 받아 3개씩 끊어 분기 그룹으로, 12개씩 끊어 연간 그룹으로 나눈 후, 각 그룹의 평균을 계산해 반환하는 JavaScript 함수를 작성하는 것입니다.
위 배열을 그룹화하면 다음과 같은 형태가 됩니다.
const quarterly = [[1,2,2],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18],[19,20]]; const yearly = [[1,2,2,4,5,6,7,8,9,10,11,12],[13,14,15,16,17,18,19,20]];
해결 방법: reduce() 활용하기
핵심 아이디어는 간단합니다. 배열을 순회하면서 지정된 크기(num)만큼 요소를 하나의 그룹으로 묶고, 각 그룹의 합계를 누적하는 것입니다. JavaScript의 reduce() 메서드를 사용하면 이 과정을 매우 깔끔하게 처리할 수 있습니다.
전체 코드는 다음과 같습니다.
const arr = [1,2,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
const findAverages = arr => {
const quarterLength = 3, yearLength = 12;
// num 크기만큼 그룹을 나누어 각 그룹의 합계를 구하는 함수
const sumOfGroup = (arr, num) => {
return arr.reduce((acc, val, ind) => {
if (ind % num === 0){
acc.push(0);
};
acc[acc.length - 1] += val;
return acc;
}, []);
};
const quarters = sumOfGroup(arr, quarterLength);
const years = sumOfGroup(arr, yearLength);
return {
"yearlyAverage": years,
"quarterlyAverage": quarters
};
};
console.log(findAverages(arr));코드 동작 원리
sumOfGroup 함수의 동작 방식을 살펴보면 다음과 같습니다.
1. reduce()가 배열의 각 요소를 순회하면서 현재 인덱스(ind)를 그룹 크기(num)로 나눕니다.
2. 인덱스를 그룹 크기로 나눈 나머지가 0이면 새로운 그룹이 시작되는 시점이므로, 결과 배열에 0을 추가합니다.
3. 이후 모든 요소는 마지막 그룹(acc[acc.length - 1])에 계속 더해집니다.
4. 최종적으로 각 그룹별 합계가 담긴 배열이 반환됩니다.
분기는 3개월 단위(quarterLength = 3), 연간은 12개월 단위(yearLength = 12)로 설정했으므로, 같은 함수 하나로 두 가지 기준의 집계를 모두 처리할 수 있습니다.
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
{
yearlyAverage: [ 77, 132 ],
quarterlyAverage: [
5, 15, 24, 33,
42, 51, 39
]
}연간 그룹은 첫 12개 요소(1~12)의 합인 77과 나머지 8개 요소(13~20)의 합인 132로 계산되었으며, 분기별로는 5, 15, 24, 33, 42, 51, 39의 합계 값이 순서대로 출력됩니다. 만약 합계가 아닌 진짜 '평균'이 필요하다면, 각 그룹의 합을 해당 그룹의 요소 개수로 나누어 주기만 하면 됩니다.
마무리
이처럼 reduce()와 인덱스 연산만 활용하면 별도의 외부 라이브러리 없이도 배열을 원하는 주기 단위로 그룹화하고 집계할 수 있습니다. 월별 매출 데이터, 센서 로그 등 시계열 데이터를 분기·연간 단위로 요약해야 할 때 유용하게 활용해 보시기 바랍니다.