숫자로만 이루어진 리스트가 있을 때, 첫 번째 요소부터 시작해 한 칸씩 이동하면서 길이가 n인 연속 구간의 평균을 차례대로 구하는 방법을 알아보겠습니다. 흔히 말하는 '슬라이딩 윈도우' 방식으로, 시계열 데이터에서 이동평균을 계산할 때 자주 쓰이는 패턴입니다.
예시
아래 예시는 리스트에서 길이 4인 연속 요소들의 평균을 구하는 과정을 단순화해 보여줍니다.
주어진 리스트: [10, 12, 14, 16, 18, 20, 22, 24, 26] 4개씩 연속된 숫자 구간의 평균: [13.0, 15.0, 17.0, 19.0, 21.0, 23.0]
방법 1: sum()과 range() 활용
리스트 컴프리헨션과 range()를 조합해 각 구간의 시작 인덱스를 하나씩 순회합니다. 슬라이싱으로 해당 구간을 추출한 뒤 sum()으로 합계를 구하고, 구간 길이로 나누면 평균이 됩니다. 최종 결과는 새로운 리스트에 담깁니다.
여기서 핵심은 range(len(listA) - seg + 1) 부분입니다. 마지막 구간까지 빠짐없이 포함하려면 전체 길이에서 구간 길이를 뺀 값에 1을 더해야 하기 때문입니다.
listA = [10, 12, 14, 16, 18, 20, 22, 24, 26]
print("주어진 리스트:\n", listA)
seg = 4
# 리스트 컴프리헨션
res = [sum(listA[m:m + seg]) / seg
for m in range(len(listA) - seg + 1)]
print("평균값이 담긴 새 리스트:\n ", res)
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
주어진 리스트:
[10, 12, 14, 16, 18, 20, 22, 24, 26]
평균값이 담긴 새 리스트:
[13.0, 15.0, 17.0, 19.0, 21.0, 23.0]
방법 2: islice와 mean 활용
파이썬 표준 라이브러리를 활용하면 더 직관적으로 구현할 수 있습니다. itertools의 islice()로 리스트를 서로 다른 시작 위치부터 잘라낸 뒤 zip()으로 묶으면 연속 구간들이 자동으로 만들어지고, map()으로 각 구간에 statistics의 mean()을 적용해 평균을 구합니다.
from statistics import mean
from itertools import islice
listA = [10, 12, 14, 16, 18, 20, 22, 24, 26]
print("주어진 리스트:\n", listA)
# islice와 mean 활용
listB = zip(*(islice(listA, i, None) for i in range(4)))
res = list(map(mean, listB))
print("평균값이 담긴 새 리스트:\n ", res)
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
주어진 리스트:
[10, 12, 14, 16, 18, 20, 22, 24, 26]
평균값이 담긴 새 리스트:
[13, 15, 17, 19, 21, 23]
statistics.mean()은 정수 입력에 대해 나누어떨어질 경우 정수형으로 반환하기 때문에, 첫 번째 방법의 13.0과 달리 13으로 표시됩니다. 값 자체는 동일합니다.
정리
두 방법 모두 동일한 결과를 내지만 성격이 조금 다릅니다. 첫 번째 방법은 별도 모듈 없이 슬라이싱만으로 구현되어 범용적이고, 두 번째 방법은 표준 라이브러리의 통계·반복자 도구를 활용해 코드의 의도가 명확하게 드러난다는 장점이 있습니다. 실무에서 대량 데이터의 이동평균을 다룬다면 NumPy의 sliding_window_view나 pandas의 rolling().mean()을 사용하는 것이 성능 면에서 더 유리합니다.