파이썬-pandas-데이터-프레임-판다2
가만 보자. 어떤 데이터를 골라야 하나.

지난 시간에는 Python pandas 사용법으로 데이터 생성, 로딩 및 저장, 색인 관리하는 법을 알아보았습니다. 이번 시간에는 Python pandas의 데이터 프레임(DataFrame)에서 데이터를 확인하는 법, 정렬하는 법, 선택하는 법을 알아보겠습니다. 이 시점은 데이터를 준비하는 2단계로 데이터의 분석 방향을 가늠하는 분기점이라고 할 수 있습니다.

파이썬-pandas-사용법-데이터-프레임-길안내-선택-데이터-확인-정렬-선택
데이터의 분석 방향을 가늠하는 분기점 Alexander Schimmeck | Unsplash

먼저 데이터를 확인하는 법부터 알아보겠습니다.

확인하기(viewing)

데이터를 빠르게 확인할 때는 데이터의 값, 생김새, 정보, 요약 통계, 결측치를 중심으로 파악하면 좋습니다. 실습을 위해서 다음 예제 코드를 사용하겠습니다.

python
df = pd.DataFrame(np.arange(9).reshape((3,3))[::-1],
index=['연필', '공책', '시계'],
columns=['분류1', '분류2', '분류3'])
# 결과
분류1 분류2 분류3
연필 6 7 8
공책 3 4 5
시계 0 1 2

먼저 값부터 확인해보겠습니다.

1) 값: values

values 속성은 pandas DataFrame에서 값을 확인하는 도구입니다. DataFrame의 열이 서로 같은 dtype을 가졌다면 values 속성은 Series에서와 동일하게 DataFrame에 저장된 데이터를 2차원 배열로 반환합니다.

python
df.values
# 결과
array([[6, 7, 8],
[3, 4, 5],
[0, 1, 2]])

2) 생김새: shape, head, tail, sample

shape, head, tail 함수로는 데이터의 생김새를 확인할 수 있습니다. 각 함수는 데이터의 행과 열의 수, 데이터의 첫 부분, 끝 부분, 그리고 무작위로 뽑은 데이터를 확인하는 데 사용합니다.

모양: shape

shape 속성은 데이터의 행과 열의 수를 알려줍니다.

python
df.shape
# 결과
(3, 3) # 3개 행과 3개 열 = 3개의 데이터 레코드와 3개의 속성

첫 부분: head

head 메서드는 데이트의 첫 5개 행만 출력합니다.

python
df.head() # 첫 행부터 5개 행 출력

만약 출력할 행 개수를 지정하고 싶다면 원하는 행 개수를 head 메서드에 인자로 전달하면 됩니다.

python
df.head(2) # 첫 행부터 2개 행 출력

뒷 부분: tail

tail 메서드는 데이터의 끝 부터 5개 행을 출력합니다. tail 함수 역시 인자로 출력할 행의 개수를 지정할 수 있습니다.

python
df.tail() # 맨 마지막 행부터 5개 행 출력
df.tail(7) # 맨 마지막 행부터 7개 행 출력

무작위: sample

sample 함수는 데이터에서 임의의 n개의 행 또는 열을 무작위로 추출하는 함수입니다. 이 함수는 무작위 표본 추출을 하고 싶을 때 유용하게 쓰입니다.

python
df.sample() # 임의의 1개 행 추출
df.sample(n=3) # 임의의 3개 행 추출
df.sample(n=1, axis=1) # 임의의 1개 열 추출
df.sample(frac=0.2) # 원본 데이터의 20% 만큼 데이터 비복원 추출
df.sample(frac=0.3, replace=True) # 원본 데이터의 30% 만큼 데이터 복원 추출
df.sample(frac=1.5, replace=True) # 원본 데이터의 1.5배 만큼 데이터 복원 추출
df.sample(n=2, weights='열1') # '열1'에서 값이 가장 큰 순서대로 2개 행 추출
df.sample(n=4, random_state=1) # 임의의 4개 행 추출, random_state의 숫자를 지정해 동일 결과 재추출 가능

3) 정보: info

info 메서드는 DataFrame의 각 열의 정보를 알려줍니다.

python
df.info()
# 결과
<class 'pandas.core.frame.DataFrame'>
Index: 3 entries, 연필 to 시계
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 분류1 3 non-null int32
1 분류2 3 non-null int32
2 분류3 3 non-null int32
dtypes: int32(3)
memory usage: 60.0+ bytes

4) 요약 통계: describe

describe 메서드는 DataFrame에서 여러 개의 통계 결과를 한 번에 만들어냅니다. 여기서 결측치는 제외되고 계산됩니다. pandas에서 모든 기술 통계를 계산할 때는 누락된 데이터를 배제하고 처리합니다.

python
df.describe()
# 결과
분류1 분류2 분류3
count 3.0 3.0 3.0
mean 3.0 4.0 5.0
std 3.0 3.0 3.0
min 0.0 1.0 2.0
25% 1.5 2.5 3.5
50% 3.0 4.0 5.0
75% 4.5 5.5 6.5
max 6.0 7.0 8.0

요약 통계와 관련한 다른 메서드는 이 시리즈의 마지막 편인 데이터 집계와 연산 부분에서 자세히 살펴보도록 하겠습니다.

5) 결측치: isnull, notnull

isnullnotnull은 누락된 데이터를 찾을 때 사용합니다.

isnull

누락된 값이 없으면 False를 반환합니다.

python
pd.isnull(df)
# 결과
분류1 분류2 분류3
연필 False False False
공책 False False False
시계 False False False

만약 전체 데이터 프레임에서 결측된 값의 개수를 알고 싶다면 아래와 같이 isnull().sum()을 사용하면 됩니다.

python
df.isnull().sum()
# 결과
분류1 0
분류2 0
분류3 0
dtype: int64

notnull

notnullisnull과 반대되는 메서드입니다. 누락된 값이 없으면 True를 반환합니다.

python
pd.notnull(df)
#결과
분류1 분류2 분류3
연필 True True True
공책 True True True
시계 True True True

결측치를 처리하는 일은 중요합니다. 결측치를 어떻게 다루느냐에 따라 최종 결과에 영향을 주기 때문입니다. 결측치를 정제하는 작업은 데이터 병합, 정제, 변형하는 법에서 자세히 다루도록 하겠습니다.

지금까지는 데이터를 확인하는 법을 알아보았습니다. 다음은 데이터를 정렬하는 법을 알아보겠습니다.

정렬하기(aligning)

데이터를 정렬하면 분류가 쉬워집니다. 정리가 잘된 데이터는 분석의 효율성을 높입니다.

pandas-데이터-정렬-자료-책장
데이터를 인덱스에 따라 정렬하기 Garmin B | Unsplash

데이터 정렬은 값 정렬과 순위 매기기로 나뉩니다. 색인 정렬은 데이터 생성, 로딩 및 저장, 색인 관리하는 법의 '색인 관리' 부분을 참조해주세요.

1) 값: sort_values

값에 따라 데이터를 정렬하고 싶다면 sort_values 메서드를 사용하면 됩니다. 아래는 열 1개에 따라 데이터를 정렬하는 코드입니다.

python
df.sort_values('분류2')
df.sort_values(by='분류2') # 열 이름이 '분류2'인 열을 따라 정렬
# 결과
분류1 분류2 분류3
연필 0 1 2
공책 3 4 5
시계 6 7 8

여러 개의 열을 정렬하려면 열 이름이 담긴 배열 객체를 전달하면 됩니다. 정렬할 때 비어있는 값이 있다면 누락값은 가장 마지막에 위치합니다.

python
df.sort_values(by=['분류2', '분류1']) # '분류2', '분류1' 를 기준으로 오름차순 정렬
# 결과
분류1 분류2 분류3
연필 0 1 2
공책 3 4 5
시계 6 7 8

값은 기본적으로 오름차순으로 정렬됩니다. 만약 내림차순으로 정렬하고 싶다면 ascending 옵션에 False 값을 주면 됩니다. ascending 옵션을 아래와 같이 열 마다 다르게 줄 수도 있습니다.

python
df.sort_values(['분류1', '분류2'], ascending=[True, False])

2) 순위: rank

순위를 매겨서 정렬하고 싶다면 rank 메서드를 사용하면 됩니다. 이 함수는 1부터 배열의 유효한 데이터 개수까지 순서를 매깁니다. 예제를 통해 동률 처리법을 알아보겠습니다.

python
data = {'포켓몬명': ['피카츄', '파이리', '꼬부기', '잠만보'],
'수면시간': [7, 5, 8, 18],
'능력치': [40, 60, 80, 90]}
df2 = pd.DataFrame(data).set_index('포켓몬명') # 행 색인명 지정
# 결과
수면시간 능력치
포켓몬명
피카츄 7 40
파이리 5 60
꼬부기 8 80
잠만보 18 90

같은 열에서 행에 따라 순위 매기기

rank 메서드에 옵션이 없으면 같은 열에서 행에 따라 순위를 매깁니다.

python
df2.rank()
# 결과
수면시간 능력치
포켓몬명
피카츄 2.0 1.0
파이리 1.0 2.0
꼬부기 3.0 3.0
잠만보 4.0 4.0

같은 행에서 열에 따라 순위 매기기

axis=1 옵션을 주면 같은 행에서 열에 따라 순위를 매기죠.

python
df2.rank(axis=1)
# 결과
수면시간 능력치
포켓몬명
피카츄 1.0 2.0
파이리 1.0 2.0
꼬부기 1.0 2.0
잠만보 1.0 2.0

순위는 기본적으로 오름차순으로 매겨집니다. 내림차순으로 순위를 매길 수도 있습니다.

내림차순으로 순위 매기기

내림차순으로 순위를 매기고 싶다면 ascending=False 옵션을 지정하면 됩니다.

python
df2.rank(ascending=False)

위에서 살펴보았듯이 rank 메서드의 기본 옵션은 method=average입니다. 동점 관측치에 대해서 평균 순위를 부여하는 옵션이죠. 동률 처리 메서드의 다른 옵션으로는 먼저 나타난 값에 순위 부여하기, 최소 순위 부여하기, 최대 순위 부여하기, 순위 간 차이를 1씩 증가하도록 설정하는 옵션이 있습니다. 어떤 옵션을 주느냐에 따라 같은 관측치라도 다른 순위를 가질 수 있습니다. 상황별로 사용할 수 있는 옵션은 다음과 같습니다.

  • 동점인 값 사이에서 먼저 나타난 관측치에 높은 순위를 매기려면? method='first'
  • 동점인 값 사이에서 최소 순위를 매기려면? method='min'
  • 동점인 값 사이에서 최대 순위를 매기려면? method='max'
  • 순위를 1씩 증가하게 하려면? method='dense'

지금까지 데이터를 값에 따라 정렬하고 순위를 매기는 법을 알아보았습니다. 지금부터는 데이터를 선택하는 법을 살펴보겠습니다.

선택하기(selecting): 기본

데이터를 선택하는 일은 자원을 집중할 곳을 찾는 일입니다. 마치 안경을 쓰고 중요한 부분에 시선을 두는 것과도 같습니다.

pandas-데이터-선택-안경-강아지
어떤 데이터를 선택할까? Jamie Street | Unsplash

데이터를 선택할 때는 인덱싱(indexing)과 슬라이싱(slicing) 방법을 사용합니다. 인덱싱은 색인을 이용해 특정 위치에 맵핑(mapping)된 값을 가져오는 작업입니다. 인덱싱에는 대괄호([]), loc, iloc를 사용하는 방법이 있습니다. 슬라이싱은 지정한 두 위치 사이에 있는 색인에 맵핑된 값을 가져오는 작업입니다.

이어 살펴볼 데이터 선택은 두 부분으로 나뉩니다. 하나는 데이터를 선택하는 기본 방법이고 다른 하나는 목적에 따라 데이터를 선택하는 방법입니다. 데이터 선택(기본)에서는 인덱싱 중 대괄호([])를 사용해 데이터를 선택하는 법과 슬라이싱을 통해 데이터를 가져오는 방법을 살펴보겠습니다. 이후 데이터 선택(목적별)에서는 lociloc와 같이 데이터를 특정 목적에 따라 선택하는 방법을 알아보겠습니다.

먼저 대괄호를 이용해 데이터를 선택해보겠습니다.

1) 인덱싱: 대괄호 []

색인을 통해 데이터를 선택하는 첫 번째 방법은 라벨 색인을 이용하는 것입니다.

라벨 색인

먼저 DataFrame의 열에 각각 사전 형식의 표기법과 속성 형식으로 접근해 데이터를 선택해보겠습니다.

python
df2['수면시간'] # 사전 형식의 표기법으로 접근해 라벨 색인으로 하나의 열값 가져오기
df2.수면시간 # 속성 형식으로 접근해 라벨 색인으로 하나의 열값 가져오기
# 결과
포켓몬명
피카츄 7
파이리 5
꼬부기 8
잠만보 18
Name: 수면시간, dtype: int64
df2['수면시간']['꼬부기'] # 꼬부기 수면시간
# 결과
8

df['열이름'] 형태로 사용하는 것은 어떤 열이든 가능합니다. 하지만 df.column 형태로 사용하는 것은 파이썬에서 사용가능한 변수 이름 형식일 때만 가능합니다.

만일 두 개 이상의 컬럼을 가져오고 싶다면 아래 코드에서처럼 리스트를 대괄호로 한 번 더 감싸주면 됩니다.

python
df2[['수면시간', '능력치']] # 색인으로 하나 이상의 컬럼 값 가져오기
# 결과
수면시간 능력치
포켓몬명
피카츄 7 40
파이리 5 60
꼬부기 8 80
잠만보 18 90
df2['능력치'][['피카츄', '꼬부기']]
# 결과
포켓몬명
피카츄 40
꼬부기 80
Name: 능력치, dtype: int64

인덱싱으로 새로운 값을 대입할 수도 있습니다.

python
df2['수면시간']['피카츄', '잠만보'] = 5
# 결과
수면시간 능력치
포켓몬명
피카츄 5 40 # 7에서 5로 변경됨
파이리 5 60
꼬부기 8 80
잠만보 5 90 # 18에서 5로 변경됨

다음은 정수 색인을 이용해 데이터를 선택해보겠습니다.

정수 색인

python
df2.columns[0] # 정수 색인 0인 열의 이름 가져오기
# 결과
'수면시간'
df[df.columns[0]] # 맨 처음 열 가져오기
# 결과
포켓몬명
피카츄 7
파이리 5
꼬부기 8
잠만보 18
Name: 수면시간, dtype: int64
df[df.columns[-1]] # 맨 끝 열 가져오기
# 결과
포켓몬명
피카츄 40
파이리 60
꼬부기 80
잠만보 90
Name: 능력치, dtype: int64

다음과 같이 라벨 색인과 정수 색인을 모두 이용할 수도 있죠.

python
df2['수면시간'][3] # 잠만보 수면시간
# 결과
18

지금까지 대괄호를 이용해 데이터를 선택하는 법을 알아보았습니다. 이번에는 슬라이싱을 통해 원하는 범위 사이에 위치한 값을 선택하는 법을 알아보겠습니다.

2) 슬라이싱: 쌍점(:)

슬라이싱을 할 때는 쌍점(colon)을 사용합니다. 슬라이싱 역시 인덱싱처럼 라벨 색인과 정수 색인을 이용해 데이터를 선택할 수 있습니다.

라벨 색인

라벨 이름으로 슬라이싱하면 시작 색인과 끝 색인에 맵핑된 값을 모두 포함해서 출력합니다.

python
df2['수면시간']['피카츄':'꼬부기']
# 결과
포켓몬명
피카츄 7
파이리 5
꼬부기 8
Name: 수면시간, dtype: int64

정수 색인

정수 색인으로 슬라이싱을 할 때는 라벨 색인을 슬라이싱 할 때와 다릅니다. 정수 색인 슬라이싱에서는 첫 번째 나오는 숫자에 맵핑된 값은 포함하지만 마지막 정수에 맵핑된 값은 포함하지 않습니다.

python
df2['수면시간'][1:3] # 1행 파이리, 2행 꼬부기
# 결과
포켓몬명
파이리 5
꼬부기 8
Name: 수면시간, dtype: int64
df2['포켓몬명'][:2]
# 결과
포켓몬명
피카츄 7
파이리 5
Name: 수면시간, dtype: int64

지금까지 라벨 색인과 정수 색인을 이용해 데이터를 선택하는 기본 방법을 알아보았습니다. 그럼 데이터를 목적별로 선택하는 방법에는 어떤 것들이 있는지 함께 살펴볼까요?

선택하기(selecting): 목적별

목적과 상황에 맞게 데이터를 선택하는 법에는 loc(라벨 색인 이용), iloc(정수 색인 이용), 조건 선택, 유일값 선택(unique), 유일값과 도수 계산(value_counts) 및 값 골라내기(isin)로 나뉩니다. 다음 예제를 활용해 데이터를 목적에 따라 선택하는 법을 알아보겠습니다.

python
data = {'포켓몬명': ['피카츄', '파이리', '꼬부기', '잠만보', '이상해씨'],
'과': ['이과', '문과', '이과', '이과', '예체능'],
'수면시간': [7, 5, 8, 18, 7],
'능력치': [40, 60, 80, 90, 99]}
df3 = pd.DataFrame(data).set_index('포켓몬명')

1) 라벨 색인: loc

loc 속성을 사용하면 라벨 색인을 통해 행에 접근할 수 있습니다.

인덱싱

python
df3.loc['잠만보'] # 행 색인 '잠만보'에 해당하는 행 반환
# 결과
과 문과
수면시간 18
능력치 90
Name: 잠만보, dtype: object

라벨로 하나의 행과 여러 열을 선택하려면 다음 코드를 사용하면 됩니다.

python
df3.loc['잠만보', ['수면시간', '능력치']]
# 결과
수면시간 18
능력치 90
Name: 잠만보, dtype: object

슬라이싱

다음은 loc를 사용해 라벨 색인으로 슬라이싱을 하는 예제입니다.

python
df3.loc[:'꼬부기', '능력치'] # 꼬부기까지 포함
# 결과
포켓몬명
피카츄 40
파이리 60
꼬부기 80
Name: 능력치, dtype: int64

2) 정수 색인: iloc

인덱싱

iloc는 정수 색인을 사용해 특정 값에 접근할 수 있습니다.

python
df3.iloc[2] # 3번 째 행 꼬부기
# 결과
과 이과
수면시간 8
능력치 80
Name: 꼬부기, dtype: object

정수 색인으로 다수의 행과 열을 선택하려면 다음 코드를 사용하면 됩니다.

python
df3.iloc[2, [2, 0, 1]]
# 결과
능력치 80
과 이과
수면시간 8
Name: 꼬부기, dtype: object
df3.iloc[[1, 3], [2, 0, 1]]
# 결과
능력치 과 수면시간
포켓몬명
파이리 60 문과 5
잠만보 90 문과 18

슬라이싱

이번에는 iloc를 사용해 정수 색인으로 슬라이싱을 하는 예제를 살펴보죠.

python
df3.iloc[1:3, 0:2]
# 결과
과 수면시간
포켓몬명
파이리 문과 5
꼬부기 이과 8

3) 조건

조건에 해당하는 데이터를 선택할 수도 있습니다. 먼저 조건이 1개인 경우를 살펴보겠습니다.

조건 1개

대괄호 []
python
df3['수면시간'] >= 7 # 수면 시간이 7시간이 넘는지의 여부를 불리언 값으로 반환
# 결과
포켓몬명
피카츄 True
파이리 False
꼬부기 True
잠만보 True
이상해씨 True
Name: 수면시간, dtype: bool

이 조건을 DataFrame에서 데이터를 선택하는 필터(filter)처럼 사용할 수도 있습니다.

python
filt = (df3['수면시간'] > 7)
df3[filt]
또는
df3[df3['수면시간'] > 7]
# 결과
과 수면시간 능력치
포켓몬명
꼬부기 이과 8 80
잠만보 이과 18 90

만약 특정 조건에 해당하지 않는 데이터를 선택하고 싶다면 물결 기호(~)를 사용하시면 됩니다.

python
filt = (df3['수면시간'] > 7)
df3[~filt]
# 결과
과 수면시간 능력치
포켓몬명
피카츄 이과 7 40
파이리 문과 5 60
이상해씨 예체능 7 99
loc

loc를 사용해서 조건에 따라 데이터를 선택할 수도 있습니다.

python
df3.loc[df3['수면시간'] > 7, '능력치'] # 1개 열 가져오기
# 결과
포켓몬명
꼬부기 80
잠만보 90
Name: 능력치, dtype: int64
df3.loc[df3['수면시간'] > 7, ['능력치', '과']] # 2개 열 가져오기
# 결과
능력치 과
포켓몬명
꼬부기 80 이과
잠만보 90 이과
iloc

iloc를 사용할 수도 있죠.

python
df3.iloc[:, :2][df3['수면시간'] > 7]
# 결과
과 수면시간
포켓몬명
꼬부기 이과 8
잠만보 문과 18

지금까지 조건이 1개인 경우에 데이터를 선택하는 법을 알아보았습니다. 지금부터는 조건이 2개 이상인 경우를 살펴보겠습니다.

조건 2개 이상

먼저 조건이 2개 이상일 경우는 n개 조건을 모두 만족시키는 '그리고(&)'인 경우와 n개 조건 중 하나만 만족시켜도 되는 '또는(|)'인 경우가 있습니다.

그리고: &

'&' 기호는 양 조건을 모두 만족시키는 데이터를 선택하고 싶을 때 사용합니다.

python
df3.loc[(df3['수면시간'] > 7) & (df3['과'] == '이과')]
# 결과
과 수면시간 능력치
포켓몬명
꼬부기 이과 8 80
잠만보 이과 18 90
또는: |

'|' 기호는 양 조건 중에 한 조건만 만족시켜도 되는 데이터를 선택하고 싶을 때 사용합니다.

python
df3.loc[(df3['수면시간'] > 7) | (df3['과'] == '이과')]
# 결과
과 수면시간 능력치
포켓몬명
피카츄 이과 7 40
꼬부기 이과 8 80
잠만보 이과 18 90

문자열 값: startswith, endswith

특정 문자열로 시작하는 데이터를 선택하고 싶으면 startswith, 특정 문자열로 끝나는 데이터를 선택하고 싶으면 endswith를 사용하면 됩니다.

시작: startswith
python
filt = df3['과'].str.startswith('이') # '이'로 시작
df3[filt]
# 결과
과 수면시간 능력치
포켓몬명
피카츄 이과 7 40
꼬부기 이과 8 80
잠만보 이과 18 90
끝: endswith
python
filt = df3['과'].str.endswith('능') # '능'으로 끝남
df3[filt]
# 결과
과 수면시간 능력치
포켓몬명
이상해씨 예체능 7 99

포함: contains

특정 문자열을 포함하는 데이터를 선택하고 싶다면 contains 메서드를 사용하면 됩니다.

python
df3['과'].str.contains('문')
# 결과
포켓몬명
피카츄 False
파이리 True
꼬부기 False
잠만보 False
이상해씨 False
Name:, dtype: bool

여기에 na 옵션을 주면 결측치를 어떻게 처리할 것인지 선택할 수 있습니다. True 값을 전달하면 NaN인 데이터는 True 값이 됩니다. contains 메서드를 다음과 같이 조건 필터처럼 사용할 수도 있죠.

python
filt = df3['과'].str.contains('문') # '문' 포함
df3[filt]
# 결과
과 수면시간 능력치
포켓몬명
파이리 문과 5 60
df3[~filt] # '과'에 '문'이 들어가는 데이터 제외
# 결과
과 수면시간 능력치
포켓몬명
파이리 문과 5 60
이상해씨 예체능 7 99

4) 유일값: unique, nunique

데이터에서 고유한 값을 알고 싶다면 unique, nunique를 사용할 수 있습니다. 전자는 유일값의 종류를 후자는 유일값의 개수를 알려줍니다.

종류

unique 메서드는 열에서 중복되는 값을 제거하고 유일값만 담고 있는 Series를 반환합니다.

python
df3['과'].unique()
# 결과
array(['이과', '문과', '예체능'], dtype=object)

유일값은 정렬된 순서로 반환되지 않습니다. 만약 값을 정렬하고 싶다면 유일값을 추출해 변수에 할당한 뒤에 sort() 함수를 사용해야 합니다.

python
uniques = df3['과'].unique()
uniques.sort()
# 결과
array(['문과', '예체능', '이과'], dtype=object)

개수

nunique 메서드는 데이터의 고유한 값의 개수를 알고싶을 때 사용합니다.

python
df['과'].nunique()
# 결과
3

5) 빈도수: value_counts

value_counts() 메서드는 Series에서 유일값에 대한 도수(frequency)를 계산하여 반환합니다. 이 메서드에서 도수는 값에 따라 내림차순으로 정렬됩니다.

기본

python
df3['과'].value_counts()
# 결과
이과 3
문과 1
예체능 1
Name:, dtype: int64
pd.value_counts(df3['과'].values, sort=False)
# 결과
이과 3
문과 1
예체능 1
Name:, dtype: int64

DataFrame의 여러 열에 대해 히스토그램(histogram)을 구하고 싶으면 apply 함수에 pd.value_counts 를 넘기면 됩니다.

python
df4 = pd.DataFrame({'1분기': [5, 3, 4, 1, 2],
'2분기': [2, 3, 5, 1, 3],
'3분기': [4, 1, 5, 2, 1]})
result = df4.apply(pd.value_counts).fillna(0)
# 결과
1분기 2분기 3분기
1 1 1.0 2.0
2 1 1.0 1.0
3 1 2.0 0.0
4 1 0.0 1.0
5 1 1.0 1.0

위에서 출력된 결과의 행 라벨은 전체 열의 유일한 값을 담고 있습니다. 각 행의 값은 각 열에서 해당 값이 몇 번 나타났는지 알려줍니다. apply에 대한 함수는 데이터 집계와 연산편에서 더 자세히 알아보겠습니다.

비율

만약 각 유일값의 도수가 전체에서 차지하는 비율을 알고 싶다면 normalize=True 옵션을 이용하면 됩니다.

python
df3['과'].value_counts(normalize=True)

6) 특정 값 유무: isin

열에서 값을 골라내고 싶을 때는 isin 메서드를 사용하면 됩니다. isin 메서드는 해당 값이 열에 있는지 파악하고 파악한 결과를 불리언 벡터로 반환합니다. isin 메서드를 이용하면 조건 필터로 유용하게 사용할 수 있습니다.

python
result = df3['과'].isin(['이과', '감자']) # '과' 열의 값으로 '이과' 또는 '감자'가 있는지를 확인
# 결과
포켓몬명
피카츄 True
파이리 False # 문과
꼬부기 True
잠만보 True
이상해씨 False # 예체능
Name:, dtype: bool
df3[result] # result를 필터로 사용
# 결과
과 수면시간 능력치
포켓몬명
피카츄 이과 7 40
꼬부기 이과 8 80
잠만보 이과 18 90
python
division = ['이과', '문과']
filt = df3['과'].isin(division) # 과가 이과 또는 문과인 포켓몬
df[filt]
# 결과
과 수면시간 능력치
포켓몬명
피카츄 이과 7 40
파이리 문과 5 60
꼬부기 이과 8 80
잠만보 이과 18 90

여기서 Index.get_indexer 메서드는 여러 값이 들어 있는 배열에서 유일한 값의 색인 배열을 구할 수 있습니다.

python
to_match = pd.Series(['셀러리', '고구마', '호박', '고구마', '감자', '고구마'])
unique_values = pd.Series(to_match.unique()) # 셀러리, 고구마, 호박, 감자 순
pd.Index(unique_values).get_indexer(to_match)
# 결과
array([0, 1, 2, 1, 3, 1], dtype=int64)

7) 그룹별 순서: groupby + cumcount

만약 같은 값끼리 그룹별로 묶어서 각 그룹 내에서 해당 값의 순서를 구하고 싶다면 데이터 재형성, 연산, 집계하는 법에서 배울 groupby 함수와 cumcount 함수를 이용하면 됩니다.

python
dfg = pd.DataFrame(list("aaaba"), columns=['열이름'])
dfg.groupby('열이름').cumcount()
# 결과
0 0 # a
1 1 # a
2 2 # a
3 0 # b
4 3 # a
dtype: int64

지금까지 Python pandas 데이터 프레임에서 데이터를 확인하는 법, 데이터를 정렬하는 법, 마지막으로 데이터를 선택하는 다양항 방법을 알아보았습니다. 다음 편에서는 Python pandas 데이터 병합, 정제, 변형하는 법을 살펴보겠습니다. 모두 수고 많으셨습니다.

참고 문헌

...

©2022 Snug Archive. All rights reserved.

Contact me at snugarchive@gmail.com.