Pandas. value_counts() 용례
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()는 "범주별로 데이터가 몇 개씩 있는지 빠르게 파악하는 함수"라고 생각하면 가장 정확합니다.
참고
- 타이타닉 데이터셋 : Titanic Dataset | Kaggle