워로디스

Pandas. value_counts() 용례 본문

Data Science/Pandas

Pandas. value_counts() 용례

워로디스 2026. 9. 28. 22:38

value_counts()는 Pandas에서 범주형 데이터의 분포를 빠르게 확인할 때 가장 자주 쓰는 함수 중 하나입니다. 핵심은 보통 DataFrame 전체보다 특정 컬럼(Series)에 사용하는 경우가 훨씬 많다는 점입니다.

1. 가장 기본적인 사용: 값별 개수 세기

df['Sex'].value_counts()

예:

Sex
male      577
female    314
Name: count, dtype: int64

해석:

  • male이 577개
  • female이 314개

즉, SQL의 GROUP BY + COUNT()와 비슷한 용도로 생각하면 됩니다.

SELECT Sex, COUNT(*)
FROM df
GROUP BY Sex;

Titanic처럼 범주형 변수가 있는 데이터에서 가장 흔하게 사용합니다.

df['Survived'].value_counts()df['Pclass'].value_counts()df['Sex'].value_counts()df['Embarked'].value_counts()

2. 비율 확인하기: normalize=True

단순 개수가 아니라 전체에서 차지하는 비율을 알고 싶을 때 많이 사용합니다.

df['Sex'].value_counts(normalize=True)

예:

male      0.647587
female    0.352413

즉,

  • 남성 약 64.8%
  • 여성 약 35.2%

퍼센트로 바로 보고 싶다면:

df['Sex'].value_counts(normalize=True) * 100
male      64.76
female    35.24

탐색적 데이터 분석(EDA)에서는 개수와 비율을 둘 다 보는 경우가 많습니다.

3. 결측치까지 포함해서 확인: dropna=False

value_counts()는 기본적으로 NaN을 제외합니다.

df['Embarked'].value_counts()

결측치도 하나의 값처럼 세고 싶다면:

df['Embarked'].value_counts(dropna=False)

예:

S      644
C      168
Q       77
NaN      2

이 방식은 데이터 전처리 전에 특히 유용합니다.

df['Cabin'].value_counts(dropna=False)

다만 결측치 개수만 알고 싶은 경우에는 보통 다음 코드가 더 명확합니다.

df['Cabin'].isna().sum()

4. 상위 빈도만 확인하기

값 종류가 아주 많을 때는 head()와 같이 사용합니다.

df['Ticket'].value_counts().head(10)

뜻은:

가장 많이 등장한 Ticket 값 10개를 보여줘.

실무에서는 로그 데이터나 상품 데이터처럼 값 종류가 많은 컬럼에서 많이 사용합니다.

df['country'].value_counts().head(10)df['product'].value_counts().head(20)df['error_code'].value_counts().head(10)

5. 적게 등장하는 값 찾기

기본값은 빈도가 높은 순으로 정렬됩니다.

반대로 적게 등장하는 값을 보고 싶다면:

df['Embarked'].value_counts(ascending=True)

또는:

df['Ticket'].value_counts().tail()

희귀 카테고리를 찾거나 이상 데이터를 검사할 때 유용합니다.

6. 두 개 이상의 컬럼 조합 세기

이 경우는 DataFrame.value_counts()의 매우 유용한 사용법입니다.

df[['Sex', 'Survived']].value_counts()

예를 들어 결과가:

Sex     Survived
male    0           468
female  1           233
male    1           109
female  0            81

라면:

  • 남성 + 사망: 468명
  • 여성 + 생존: 233명
  • 남성 + 생존: 109명
  • 여성 + 사망: 81명

이라는 의미입니다.

세 개 이상의 조건도 가능합니다.

df[['Pclass', 'Sex', 'Survived']].value_counts()

이렇게 하면:

객실 등급 × 성별 × 생존 여부

조합별 인원을 볼 수 있습니다.

7. 조합별 비율 보기

여기에서도 normalize=True를 사용할 수 있습니다.

df[['Sex', 'Survived']].value_counts(normalize=True)

주의할 점은 이 값이 전체 데이터에서 해당 조합이 차지하는 비율이라는 것입니다.

예를 들어:

male    0    0.525
female  1    0.261
...

라면

전체 승객의 약 52.5%가 male + Survived=0

이라는 뜻입니다.

이것은 남성의 사망률과는 다른 개념입니다.

남성 중 몇 %가 사망했는지를 알고 싶다면 crosstab()이나 groupby()가 더 적합합니다.

pd.crosstab(    df['Sex'],    df['Survived'],    normalize='index')

8. 숫자 데이터를 구간으로 나누어 세기: bins

숫자형 컬럼에도 사용할 수 있습니다.

df['Age'].value_counts(bins=5)

그러면 Age의 범위를 5개 구간으로 나누어 각 구간의 데이터 개수를 보여줍니다.

개념적으로는:

(0, 16]     ...
(16, 32]    ...
(32, 48]    ...
(48, 64]    ...
(64, 80]    ...

처럼 볼 수 있습니다.

다만 실제 분석에서는 구간을 직접 정의하는 경우가 많습니다.

pd.cut(    df['Age'],    bins=[0, 10, 20, 30, 40, 50, 60, 100]).value_counts().sort_index()

이렇게 하면 연령대별 인원 분포를 확인할 수 있습니다.

9. 데이터가 정상적으로 들어왔는지 검사

value_counts()는 단순 통계뿐 아니라 데이터 품질 검사에도 매우 자주 사용합니다.

예를 들어 성별 컬럼이 원래:

male
female

두 종류만 있어야 한다고 가정해봅시다.

df['Sex'].value_counts(dropna=False)

그런데 결과가:

male       570
female     310
Male         5
FEMALE       3
unknown      2
NaN          1

처럼 나온다면 문제가 있다는 것을 바로 알 수 있습니다.

즉, value_counts()는 다음과 같은 문제를 찾는 데 좋습니다.

  • 오타
  • 대소문자 불일치
  • 예상하지 못한 카테고리
  • 결측치
  • 비정상적으로 적은 값
  • 특정 값으로의 지나친 쏠림

10. 클래스 불균형 확인

머신러닝에서는 타깃 변수에 거의 필수적으로 사용합니다.

df['Survived'].value_counts()

그리고:

df['Survived'].value_counts(normalize=True)

예를 들어:

0    0.616
1    0.384

라면 타깃 클래스가:

  • 사망 61.6%
  • 생존 38.4%

정도로 구성되어 있다는 것을 알 수 있습니다.

불균형이 심하면 모델 평가 방법이나 샘플링 전략을 고려해야 하기 때문에 중요한 확인 과정입니다.

11. nunique()와 구분하기

초보 때 자주 헷갈리는 함수입니다.

df['Embarked'].nunique()

결과:

3

이건 단순히:

서로 다른 값이 몇 종류인가?

를 계산합니다.

반면:

df['Embarked'].value_counts()

는:

각각의 값이 몇 개씩 있는가?

를 보여줍니다.

정리하면:

코드 질문
nunique() 값이 몇 종류인가?
unique() 어떤 값들이 있는가?
value_counts() 각 값이 몇 개씩 있는가?

세 함수는 EDA에서 같이 자주 사용합니다.

df['Embarked'].unique()df['Embarked'].nunique()df['Embarked'].value_counts()

12. 결과를 일반 DataFrame으로 변환하기

value_counts() 결과는 기본적으로 Series 형태입니다.

counts = df['Sex'].value_counts()

필요하면 DataFrame으로 바꿀 수 있습니다.

df['Sex'].value_counts().reset_index()

대략:

      Sex  count
0    male    577
1  female    314

형태가 됩니다.

이렇게 하면 이후에 그래프를 만들거나 다른 데이터와 병합하기 편합니다.

자주 쓰는 패턴 모음

# 기본 빈도df['col'].value_counts()# 비율df['col'].value_counts(normalize=True)# 퍼센트df['col'].value_counts(normalize=True) * 100# 결측치 포함df['col'].value_counts(dropna=False)# 빈도 낮은 순df['col'].value_counts(ascending=True)# 상위 10개df['col'].value_counts().head(10)# 여러 컬럼의 조합df[['col1', 'col2']].value_counts()# 여러 컬럼의 조합 비율df[['col1', 'col2']].value_counts(normalize=True)# 숫자 데이터를 구간별 집계df['Age'].value_counts(bins=5)# 결과를 DataFrame으로df['col'].value_counts().reset_index()

언제 value_counts()를 쓰면 좋은가

EDA를 시작할 때 다음과 같이 생각하면 편합니다.

"이 컬럼 안에 어떤 값들이 있고, 각각 몇 개나 있을까?"

이 질문이 떠오르면 거의 value_counts()입니다.

특히 다음 컬럼에 잘 맞습니다.

Sex
Survived
Pclass
Embarked
지역
직업
상품 카테고리
회원 등급
결제 방법
디바이스 종류
에러 코드

반대로 이런 컬럼에는 별 의미가 없는 경우가 많습니다.

PassengerId
고객ID
주문번호
이름
UUID

각 행마다 거의 고유한 값이기 때문입니다.

Titanic 데이터라면

처음 데이터를 받았을 때 저는 다음 정도를 먼저 확인하는 패턴을 추천합니다.

df['Survived'].value_counts(dropna=False)df['Pclass'].value_counts(dropna=False)df['Sex'].value_counts(dropna=False)df['Embarked'].value_counts(dropna=False)

그리고 비율도 봅니다.

df['Survived'].value_counts(normalize=True)df['Pclass'].value_counts(normalize=True)df['Sex'].value_counts(normalize=True)df['Embarked'].value_counts(normalize=True)

그다음 변수 간 관계가 궁금해지면:

df[['Sex', 'Survived']].value_counts()df[['Pclass', 'Survived']].value_counts()df[['Pclass', 'Sex', 'Survived']].value_counts()

로 넘어가면 자연스럽습니다.

한 줄로 기억한다면: value_counts()는 "범주별로 데이터가 몇 개씩 있는지 빠르게 파악하는 함수"라고 생각하면 가장 정확합니다.

참고

반응형