DAX AVERAGE 함수 정리: 빈 값과 0이 평균을 바꾸는 방식

평균은 누구나 아는 개념이라 AVERAGE 함수도 쉽게 지나치기 쉽습니다. 그런데 막상 보고서에 올리면 “이 평균이 왜 이렇게 나왔지?” 싶은 순간이 옵니다. 대부분은 세 군데에서 비롯됩니다. 빈 값과 0을 어떻게 취급하는지, 합계 줄의 평균이 무엇의 평균인지, 그리고 애초에 “무엇을 한 단위로 평균 낼 것인가”입니다. 이 글에서는 AVERAGE의 기본 동작을 정리하고, 실무에서 자주 부딪히는 세 가지 평균(주문당, 고객당, 일평균)을 같은 데이터로 비교해 보겠습니다.

문법

AVERAGE( <열> )

숫자가 들어 있는 열 하나를 받아서 그 값들의 산술 평균을 돌려줍니다. Microsoft 문서에서 반환값은 소수 형태의 숫자이고, DAX Guide에서는 통화 또는 소수 형식으로 안내합니다. 열 이름은 테이블[열] 형태로 씁니다.

평균수량 = AVERAGE( Sales[수량] )

Power BI Desktop에서 측정값 만들기

이 글의 식은 모두 “측정값”으로 만들면 됩니다. 메뉴 이름은 Power BI 버전과 언어 설정에 따라 조금 다를 수 있다는 점을 먼저 말씀드립니다. 일반적인 순서는 이렇습니다.

  1. 보고서 보기에서 오른쪽 필드 창에 있는 테이블(예: Sales)을 선택합니다.
  2. 상단 리본에서 “새 측정값”(영문판은 New measure)을 누릅니다.
  3. 수식 입력줄에 평균수량 = AVERAGE( Sales[수량] )처럼 이름과 식을 적고 Enter를 누릅니다.
  4. 만든 측정값을 표 시각화로 끌어다 놓고, 상품 같은 열과 함께 놓아 값이 어떻게 나뉘는지 확인합니다.

측정값은 보고서의 각 셀이 가진 필터 상태에 맞춰 다시 계산되기 때문에, 열을 바꿔 가며 올려 보는 것이 가장 빠른 확인 방법입니다.

예제 데이터

앞선 SUM 함수 글, SUMX 함수 글과 이어지는 가상 데이터입니다. 이번에는 고객 열을 추가했습니다. 결과는 Power BI에서 돌린 화면이 아니라 계산 과정을 따라가며 직접 구한 값입니다. 실제 모델에서는 열 이름과 관계 설정에 따라 다르게 보일 수 있으니, 같은 식을 본인 데이터에 적용해서 확인해 보세요.

주문고객상품수량단가
1김노트북1120
2이마우스34
3김모니터220
4박마우스54
5이노트북2100

수량의 합은 13이고 행은 5개이니 AVERAGE( Sales[수량] )는 13 ÷ 5 = 2.6입니다.

합계 줄의 평균은 무엇의 평균일까

이 측정값을 상품별 표에 올려 보겠습니다.

상품평균수량
노트북1.5
마우스4.0
모니터2.0
합계2.6

노트북은 (1 + 2) ÷ 2 = 1.5, 마우스는 (3 + 5) ÷ 2 = 4, 모니터는 2입니다. 그런데 합계 줄은 위 세 숫자의 평균(약 2.5)이 아니라 2.6입니다. 합계 줄은 필터가 없는 상태에서 전체 5개 행의 평균을 새로 계산하기 때문입니다. “평균의 평균”을 구한 값이 아니라는 점을 알아 두면 합계 줄을 읽을 때 혼란이 줄어듭니다.

빈 값과 0은 다르다

Microsoft 문서가 따로 강조하는 부분입니다. 값이 0인 셀은 합에 더해지고 그 행도 나누는 수에 포함됩니다. 반면 빈 셀은 그 행이 아예 세어지지 않습니다. 같은 3행짜리 열로 비교해 보겠습니다.

열 값계산AVERAGE
10, 20, (빈 값)(10 + 20) ÷ 215
10, 20, 0(10 + 20 + 0) ÷ 310

데이터에서 “측정하지 않음”을 빈 값으로 두느냐 0으로 채우느냐에 따라 평균이 달라집니다. 원본 데이터를 정리할 때 이 둘을 어떻게 구분할지 먼저 정해 두는 게 좋습니다. 문서가 알려주는 나머지 규칙도 같이 정리하면 이렇습니다.

  • 열이 텍스트이면 평균을 낼 수 없어서 빈 값이 반환됩니다.
  • 열에 논리값이나 빈 셀이 섞여 있으면 그 값들은 무시됩니다.
  • 평균을 낼 행이 하나도 없으면 빈 값이 반환됩니다.

실무 시나리오 1: 주문 한 건당 평균 금액

“주문 한 건에 평균 얼마를 쓰는가”를 알고 싶다고 해 보겠습니다. 금액 열이 따로 없으니 수량 × 단가를 행마다 계산한 뒤 평균을 내야 합니다. AVERAGE는 열 하나만 받으므로 이때는 AVERAGEX를 씁니다.

평균주문금액 =
AVERAGEX(
    Sales,
    Sales[수량] * Sales[단가]
)

Microsoft 문서에서 AVERAGEX는 “테이블을 한 줄씩 돌며 식을 계산한 뒤 그 값들의 산술 평균을 낸다”고 설명합니다. 행마다 120, 12, 40, 20, 200이 계산되고 합 392를 5로 나눈 78.4가 결과입니다. 그 외 규칙은 AVERAGE를 따라서 숫자가 아닌 값은 평균에 들어가지 않습니다. DAX Guide는 AVERAGE가 내부적으로 AVERAGEX를 실행하는 것과 같고 성능 차이가 없다고 설명합니다.

여기서 한 가지 함정이 있습니다. “평균 단가”를 구하려고 단가 열에 AVERAGE를 쓰면 (120 + 4 + 20 + 4 + 100) ÷ 5 = 49.6이 나옵니다. 그런데 노트북은 3개, 마우스는 8개 팔렸습니다. 많이 팔린 마우스(단가 4)가 평균에 충분히 반영되지 않았죠. 판매 수량을 반영한 평균 단가는 총매출 ÷ 총수량입니다.

평균단가_가중 =
DIVIDE(
    SUMX( Sales, Sales[수량] * Sales[단가] ),
    SUM( Sales[수량] )
)

392 ÷ 13은 약 30.2입니다. 질문이 “주문 한 건당 평균 단가”인지, “팔린 물건 한 개당 평균 단가”인지에 따라 맞는 답이 다릅니다. 이처럼 수량이 다른 값의 평균은 가중 평균을 쓰는 것이 일반적인 방법이라고 여러 DAX 교육 자료가 설명합니다.

실무 시나리오 2: 고객 한 명당 평균 구매액

이번에는 “고객 한 명이 평균 얼마를 쓰는가”입니다. 주문 한 건이 아니라 고객 한 명이 단위라서, 고객별 총매출을 먼저 구한 뒤 그 평균을 내야 합니다. 고객 목록 위에서 AVERAGEX를 돌리고, 안에서 앞서 만든 총매출 측정값을 부르면 됩니다.

총매출 =
SUMX( Sales, Sales[수량] * Sales[단가] )

고객당평균구매액 =
AVERAGEX(
    VALUES( Sales[고객] ),
    [총매출]
)

VALUES가 현재 필터 상태의 고객 목록(김, 이, 박)을 돌려주고, AVERAGEX가 그 고객을 한 명씩 돌면서 총매출을 계산합니다. 이때 “지금 도는 고객”이 자동으로 필터로 바뀌는 컨텍스트 전환이 일어납니다. 이 개념은 CALCULATE 함수 글에서 자세히 다뤘습니다.

고객구매한 주문총매출
김1번(120), 3번(40)160
이2번(12), 5번(200)212
박4번(20)20
평균(160 + 212 + 20) ÷ 3 = 약 130.7

같은 데이터에서 주문 한 건당 평균은 78.4, 고객 한 명당 평균은 약 130.7입니다. 한 사람이 여러 번 주문하기 때문에 단위를 바꾸면 평균이 크게 달라집니다. 보고서의 제목에 “평균 매출”이라고만 적어 두면 읽는 사람이 어느 평균인지 알 수 없으니, 단위를 함께 적는 것이 좋습니다.

실무 시나리오 3: 일평균 매출의 함정

“하루 평균 얼마나 파는가”는 가장 흔한 요청이면서 가장 틀리기 쉬운 평균이기도 합니다. SQLBI에는 이 주제만 다룬 글(일평균 계산의 숨은 복잡성)이 있고, 핵심은 AVERAGEX가 빈 값은 평균에서 빼지만 0은 값으로 센다는 점입니다. 3월 1일부터 5일까지 5일 중 판매가 있는 날이 3일이라고 가정한 작은 예로 보겠습니다.

날짜3/13/23/33/43/5
매출100(판매 없음)50(판매 없음)150

총매출은 300입니다. 날짜 테이블을 돌면서 하루 매출의 평균을 내는 식을 이렇게 쓰면 어떻게 될까요.

일평균_판매일기준 =
AVERAGEX( 'Date', [총매출] )

판매가 없는 날의 총매출은 0이 아니라 빈 값입니다. 그래서 그 두 날은 평균에서 빠지고 (100 + 50 + 150) ÷ 3 = 100이 나옵니다. “판매가 있었던 날의 평균”입니다. 달력 기준 하루 평균을 원한다면 빈 값을 0으로 바꿔서 세어야 합니다.

일평균_달력기준 =
AVERAGEX( 'Date', [총매출] + 0 )

일평균_달력기준_2 =
DIVIDE( [총매출], COUNTROWS( 'Date' ) )

두 식 모두 300 ÷ 5 = 60입니다. 100과 60은 질문이 다른 두 값이지 어느 한쪽이 틀린 값이 아닙니다. 다만 현실의 보고서에서는 날짜 범위가 중간에 잘리거나, 상품 필터에 따라 판매가 시작된 날이 달라지는 경우까지 생기기 때문에 위의 단순한 식으로는 부족할 수 있습니다. SQLBI는 관측 기간의 시작과 끝을 필터와 무관하게 먼저 정하고, 그 안에서 선택된 날짜만 세는 방식을 설명합니다. 이 부분은 식이 길어서 이 글에서는 다루지 않고, 원문을 참고하시길 권합니다.

쓰지 말아야 할 때

  • 값의 크기가 크게 다른 항목을 단순 평균할 때: 평균 단가처럼 수량이 다른 값은 가중 평균이 맞는 경우가 많습니다.
  • 이미 평균인 값들의 평균: 합계 줄이나 그룹별 평균을 다시 평균 내면 원래 평균과 달라집니다.
  • 극단값이 큰 데이터: 한두 건의 큰 값이 평균을 끌어올립니다. 이럴 때는 중앙값(MEDIAN)이 대표값으로 더 알맞습니다.
  • 빈 값의 의미가 불분명한 열: “없음”인지 “아직 입력 안 됨”인지부터 정해야 합니다.

알아둘 점

  • DirectQuery 모드에서는 계산 열이나 행 수준 보안 규칙 안에서 AVERAGE를 쓸 수 없다고 Microsoft 문서에 적혀 있습니다. 측정값에서는 쓸 수 있습니다.
  • DAX Guide에 따르면 DAX에서는 AVERAGE와 AVERAGEA가 기능상 차이가 없습니다. 엑셀의 AVERAGEA와는 다르다는 점만 알아 두세요.
  • 조건이 필요하면 CALCULATE로 필터를 바꿔서 씁니다. 예를 들어 마우스만의 평균 수량은 CALCULATE( AVERAGE( Sales[수량] ), Sales[상품] = “마우스” )로 4가 됩니다.
  • 지역 설정에 따라 인수 구분자가 쉼표 대신 세미콜론일 수 있습니다. 식을 붙여 넣었는데 오류가 난다면 먼저 확인해 보세요.

자주 하는 실수

  1. 빈 값을 0이라고 생각하고 평균을 해석: 빈 행은 세어지지 않습니다.
  2. 합계 줄을 “평균의 평균”으로 읽기: 합계 줄은 전체 행 기준으로 다시 계산한 값입니다.
  3. 단가 같은 비율 값을 단순 평균: 수량이 다르면 가중 평균이 맞는 경우가 많습니다.
  4. 텍스트 열에 AVERAGE: 숫자 열에 써야 하고, 텍스트 열이면 빈 값이 나옵니다.
  5. 일평균을 판매일 기준으로 구하고 달력 기준이라고 믿기: 빈 날이 평균에서 빠집니다.

비슷한 함수

  • AVERAGEX: 행마다 식을 계산한 뒤 평균
  • SUM, SUMX: 합계. 평균은 합계 ÷ 개수의 관계입니다.
  • MEDIAN: 평균 대신 중앙값이 필요할 때

정리

AVERAGE 자체는 단순하지만 결과를 읽을 때는 네 가지를 확인하세요. 빈 값이 몇 개인지, 합계 줄이 무엇의 평균인지, 평균의 단위가 주문인지 고객인지 날짜인지, 단순 평균이 질문에 맞는 평균인지입니다. 이 네 가지를 구분하면 평균 때문에 숫자가 어긋나는 일이 크게 줄어듭니다. 예제는 가상 데이터이니 본인 모델의 열 이름으로 바꿔 직접 확인해 보시고, 동작은 버전에 따라 다를 수 있어 공식 문서도 함께 보시길 권합니다.

참고한 자료

  • Microsoft Learn, AVERAGE function (DAX): https://learn.microsoft.com/en-us/dax/average-function-dax
  • Microsoft Learn, AVERAGEX function (DAX): https://learn.microsoft.com/en-us/dax/averagex-function-dax
  • DAX Guide, AVERAGE: https://dax.guide/average/
  • DAX Guide, AVERAGEX: https://dax.guide/averagex/
  • SQLBI, The hidden complexity of a daily average in DAX: https://www.sqlbi.com/articles/the-hidden-complexity-of-a-daily-average-in-dax/

“DAX AVERAGE 함수 정리: 빈 값과 0이 평균을 바꾸는 방식”에 대한 2개의 생각

댓글 남기기