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

지난 시간에는 파이썬 pandas 사용법의 첫 번째 시리즈로 [데이터 생성, 로딩 및 저장, 색인 관리하는 법][]을 알아보았습니다. 이번 시간에는 DataFrame(데이터 프레임) 안에 들어있는 데이터를 확인하고 정렬 및 선택하는 법을 알아보겠습니다.

데이터의 분석 방향을 가늠하는 분기점
데이터의 분석 방향을 가늠하는 분기점 Alexander Schimmeck - Unsplash

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

확인하기(Viewing)

데이터는 크게 2가지 관점에서 확인할 수 있습니다. 하나는 데이터의 전체 그림을 파악하는 것이고, 다른 하나는 데이터의 결측치(missing values)를 확인하는 것입니다. 데이터의 전체 그림을 확인하는 일은 데이터의 처리 방향을 판단하기 위해 필요합니다. DataFrame을 이루는 전체 행과 열의 개수, 열 이름, 요약값 등을 확인하는 작업은 모두 데이터의 개요를 살펴보는 일입니다.

반면, 데이터의 결측치를 파악하는 작업은 최종 결과에 영향을 줄 수 있는 요소를 관리하는 것입니다. 결측치를 처리하는 것은 중요합니다. 결측치를 어떻게 처리하는지에 따라 최종 결과가 완전히 달라질 수 있습니다. 실습을 통해 살펴보겠습니다. 사용할 예제 DataFrame(데이터 프레임)은 다음과 같습니다.

python
data = {'포켓몬명': ['피카츄', '파이리', '꼬부기', '잠만보'],
'수면시간': [7, 5, 8, 18],
'능력치': [40, 60, 80, 90],
'과': ['이과', '문과', '이과', '문과']}
df = pd.DataFrame(data).set_index('포켓몬명') # 행 색인명 지정
df
실습에 사용할 데이터프레임 예제
실습에 사용할 데이터프레임 예제  - Snug Archive
위 DataFrame 처럼 자료가 적으면 DataFrame의 모든 행이 출력됩니다. 그러나 DataFrame이 60행을 넘기면 첫 부분과 끝 부분에서 각각 5행씩 총 10행만 보입니다. 또, 20열을 넘으면 좌우로 10열씩 총 20열만 나타납니다. 중간의 데이터는 생략되어 표시되지 않습니다. 만일 행과 열을 생략하지 않고 모두 출력하고 싶다면 다음과 같은 옵션을 고려할 수 있습니다.
python
pd.set_option('display.max_rows', None) # DataFrame의 모든 행 출력
pd.set_option('display.max_columns', None) # DataFrame의 모든 열 출력

만일 위 설정을 되돌리고 싶다면 pd.reset_option() 패키지 함수를 사용하면 됩니다.

python
pd.reset_option('display.max_rows') # 행 출력 제한 기본값으로 되돌리기
pd.reset_option('display.max_columns') # 열 출력 제한 기본값으로 되돌리기
pd.reset_option('all') # 행 및 열 출력 제한 모두 기본값으로 되돌리기

모든 속성(attribute)과 메서드(method)는 pandas.DataFrame 클래스에 속합니다. 속성은 변수가 지니고 있는 값을 의미합니다. 메서드는 변수가 지니고 있는 함수입니다. 괄호가 없으면 속성, 괄호가 있으면 메서드라고 생각하면 됩니다.

1) 자료구조: type

변수의 자료구조를 알고 싶다면 type 함수를 이용하면 됩니다.

python
type(df)
# 결과
pandas.core.frame.DataFrame

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

shape 속성 및 head, tail, sample 메서드를 이용하면 데이터의 생김새를 확인할 수 있습니다. 각 메서드는 순서대로 데이터의 행과 열의 개수, 데이터의 첫 부분, 데이터의 끝 부분, 그리고 무작위로 뽑은 데이터를 출력합니다.

개수: shape

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

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

첫 부분: head

head 속성/메서드는 데이터의 첫 5개 행만 출력합니다.

python
df.head
# 또는
df.head() # 1행부터 5행까지 총 5개 행 출력

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

python
df.head(2) # 1행부터 2행까지 총 2개 행 출력

끝 부분: tail

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

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

무작위: sample

sample 함수는 데이터에서 임의의 n개의 행 또는 열을 무작위로 추출합니다. 이 함수는 무작위표본추출(random sampling)을 하고 싶을 때 사용됩니다.

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: 4 entries, 피카츄 to 잠만보
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 수면시간 4 non-null int64
1 능력치 4 non-null int64
24 non-null object
dtypes: int64(2), object(1)
memory usage: 128.0+ bytes

4) 요약 통계값: describe

describe 메서드는 DataFrame에서 수치로된 자료에 대한 요약 통계값을 알려줍니다. 결측치는 제외되고 계산됩니다. pandas에서 기술통계량을 계산할 때는 누락된 데이터를 배제하고 처리합니다.

python
df.describe()
# 결과
수면시간 능력치
count 4.000000 4.000000 # 빈도
mean 9.500000 67.500000 # 평균
std 5.802298 22.173558 # 표준편차
min 5.000000 40.000000 # 최솟값
25% 6.500000 55.000000 # 제1사분위수
50% 7.500000 70.000000 # 제2사분위수
75% 10.500000 82.500000 # 제3사분위수
max 18.000000 90.000000 # 최댓값

만일 문자로 된 변수의 요약 통계값도 함께 출력하려면 해당 함수에 include='all' 옵션을 주면 됩니다. 이 옵션을 사용하면 문자로 된 변수의 빈도와 고유값의 빈도 및 최빈값과 최빈값의 빈도를 파악할 수 있습니다. 각 통계량은 각각 count, unique, top, freq라는 변수명으로 출력됩니다.

python
df.describe(include='all')

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

5) 값: values

values 속성은 DataFrame에 담긴 값을 알고 싶을 때 사용합니다.

python
df.values
# 결과
array([[7, 40, '이과'],
[5, 60, '문과'],
[8, 80, '이과'],
[18, 90, '문과']], dtype=object)

참고로 색인은 index 속성으로 확인할 수 있습니다. 색인 관리에 대한 자세한 내용은 Python pandas 데이터 생성, 로딩 및 저장, 색인 관리하는 법을 참조해주세요.

python
df.index

6) 결측치: isnull, notnull

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

isnull

isnull은 누락된 데이터가 있는지를 확인하는 함수입니다. 누락된 값이 없으면 False를 반환합니다.

python
pd.isnull(df)
# 결과
수면시간 능력치 과
포켓몬명
피카츄 False False False
파이리 False False False
꼬부기 False False False
잠만보 False False False

DataFrame에서 결측값의 총 개수를 알고 싶다면 isnull().sum()을 사용하면 됩니다.

python
df.isnull().sum()
# 결과
수면시간 0
능력치 0
0
dtype: int64

notnull

notnullisnull과 반대로 누락된 데이터가 없는지를 확인합니다. 누락된 값이 없으면 "True" 값을 반환합니다.

python
pd.notnull(df)
#결과
수면시간 능력치 과
포켓몬명
피카츄 True True True
파이리 True True True
꼬부기 True True True
잠만보 True True True

여기서는 결측치를 확인하는 법만 살펴보았습니다. 결측치를 처리하는 작업은 Python pandas 데이터 병합, 정제, 변형하는 법에서 자세히 다루도록 하겠습니다. 지금까지 데이터를 확인하는 법을 알아보았습니다. 이번에는 데이터를 정렬하는 법을 알아보겠습니다.

정렬하기(Aligning)

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

데이터를 인덱스에 따라 정렬하기
데이터를 인덱스에 따라 정렬하기 Garmin B - Unsplash

데이터를 정렬하는 방법은 2가지가 있습니다. 하나는 데이터를 값의 크기에 따라 정렬하는 것이고 다른 하나는 순위를 매겨서 정렬하는 것입니다. 색인 정렬은 Python pandas 데이터 생성, 로딩 및 저장, 색인 관리하는 법의 '색인 관리' 부분을 참조해주세요.

1) 값: sort_values

값의 크기에 따라 자료를 정렬하고 싶다면 sort_values 메서드를 사용하면 됩니다. 값은 기본적으로 오름차순으로 정렬됩니다.

열 개수

1개 열

다음은 열 1개에 따라 데이터를 정렬하는 코드입니다.

python
df.sort_values('수면시간')
# 또는
df.sort_values(by='수면시간') # 열 이름이 '수면시간'인 열의 원소 크기에 따라 오름차순 정렬
# 결과
수면시간 능력치 과
포켓몬명
파이리 5 60 문과
피카츄 7 40 이과
꼬부기 8 80 이과
잠만보 18 90 문과

만약 자료가 수치가 아니라 문자라면 알파벳 A-Z순으로 정렬됩니다.

2개 열 이상

여러 개의 열을 정렬하려면 열 이름이 담긴 리스트를 전달하면 됩니다.

python
df.sort_values(by=['능력치', '수면시간']) # 열 이름을 기준으로 오름차순 정렬
# 결과
수면시간 능력치 과
포켓몬명
피카츄 7 40 이과
파이리 5 60 문과
꼬부기 8 80 이과
잠만보 18 90 문과

정렬 방법

자료를 내림차순으로 정렬하고 싶다면 ascending 옵션에 False 값을 주면 됩니다. 열마다 정렬 옵션을 다르게 하고 싶다면 ascending 매개변수에 불리언 리스트를 전달하면 됩니다.

python
# 과를 기준으로 오름차순으로 정렬한 다음 수면시간을 기준으로 내림차순 정렬
df.sort_values(['과', '수면시간'],
ascending=[True, False])

정렬할 때 비어있는 값이 있다면 누락값은 가장 마지막에 위치합니다.

2) 순위: rank

자료에 순위를 매겨서 정렬하고 싶다면 rank 메서드를 사용하면 됩니다.

열별 순위

rank 메서드는 열별로 순위를 매깁니다. 각 열은 독립적이고 같은 열 내부에서 순위를 매기는 것입니다.

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

행별 순위

axis=1 옵션을 주면 같은 행에서 순위를 매깁니다.

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

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

내림차순 순위

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

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

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

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

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

선택하기(Selecting)

데이터를 선택하는 일은 자원을 집중할 곳을 찾는 일입니다.

어떤 데이터를 선택할까?
어떤 데이터를 선택할까? Jamie Street - Unsplash

데이터를 선택하는 방법에는 인덱싱(indexing)과 슬라이싱(slicing)이 있습니다. 인덱싱은 특정 색인에 맵핑(mapping)된 값을 가져오는 작업입니다. 슬라이싱은 특정 색인 사이에 맵핑된 값을 가져오는 작업입니다. 먼저 대괄호를 이용해 데이터를 선택해보겠습니다.

1) 대괄호 []

대괄호를 이용해 데이터를 선택할 때는 라벨 색인(label index)과 정수 색인(integer index)을 이용할 수 있습니다.

라벨 색인

라벨 색인을 이용하면 특정 열을 선택할 수 있습니다. 라벨 색인을 사용하는 방법은 사전 형식과 속성 형식으로 접근하는 방법으로 나뉩니다.

python
df['수면시간'] # 사전 형식 표기법: Series로 추출
df.수면시간 # 속성 형식 표기법: Series로 추출
# 결과
포켓몬명
피카츄 7
파이리 5
꼬부기 8
잠만보 18
Name: 수면시간, dtype: int64

위 방법은 데이터를 Series 형태로 가져옵니다. 만일 DataFrame 구조를 그대로 유지하고 싶다면 열 이름을 대괄호로 한 번 더 감싸주면 됩니다.

python
df[['수면시간']] # DataFrame으로 추출

만일 특정 열에 있는 특정 인덱스에 해당하는 값을 알고 싶다면 아래와 같이 대괄호를 연이어 사용하면 됩니다.

python
df['수면시간']['꼬부기'] # 꼬부기의 수면시간 추출하기
# 결과
8

자료를 df['열이름'] 형식으로 선택하는 것은 언제나 가능합니다. 하지만 df.열이름 방식으로 열을 가져오려면 열이름이 파이썬에서 사용 가능한 형식이어야 합니다.

만일 여러 개의 열을 가져오고 싶다면 리스트를 대괄호로 한 번 더 감싸주면 됩니다.

python
df[['수면시간', '능력치']] # 여러 변수 추출하기
# 결과
수면시간 능력치
포켓몬명
피카츄 7 40
파이리 5 60
꼬부기 8 80
잠만보 18 90
python
df['능력치'][['피카츄', '꼬부기']]
# 결과
포켓몬명
피카츄 40
꼬부기 80
Name: 능력치, dtype: int64

아래와 같이 특정 값을 선택해 새로운 값으로 변경할 수도 있습니다.

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

이번에는 정수 색인을 이용해서 데이터를 선택하는 법을 알아보겠습니다.

정수 색인

python
df.columns[0] # 0번째 열이름 가져오기
# 결과
'수면시간'
python
df[df.columns[0]] # 첫 번째 열 전체 가져오기
# 결과
포켓몬명
피카츄 7
파이리 5
꼬부기 8
잠만보 18
Name: 수면시간, dtype: int64
python
df[df.columns[-1]] # 마지막 열 전체 가져오기
# 결과
포켓몬명
피카츄 이과
파이리 문과
꼬부기 이과
잠만보 문과
Name:, dtype: object

혼합

다음과 같이 정수 색인과 라벨 색인을 모두 사용해서 데이터를 선택할 수도 있습니다.

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

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

2) 쌍점(:)

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

라벨 색인

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

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

정수 색인

반면 정수 색인 슬라이싱에서는 첫 번째 인덱스에 맵핑된 값은 선택하지만 마지막 정수에 맵핑된 값은 선택하지 않습니다.

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

3) loc

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

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

아래 코드도 위 코드와 동일한 결과를 반환합니다.

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

이번에는 슬라이싱을 해보겠습니다.

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

4) iloc

iloc는 정수 색인을 사용해 특정 값에 접근하는 방법입니다.

python
df.iloc[2] # 3번째 행 꼬부기 정보 가져오기
# 결과
수면시간 8
능력치 80
Name: 꼬부기, dtype: int64

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

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

5) 조건

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

조건 1개

대괄호 []
python
df['수면시간'] >= 7 # 수면시간이 7시간 이상인 데이터 가져오기
# 결과
포켓몬명
피카츄 True
파이리 False
꼬부기 True
잠만보 True
Name: 수면시간, dtype: bool

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

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

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

python
filt = (df['수면시간'] >= 7)
df[~filt] # 수면시간이 7시간 미만인 데이터 가져오기
# 결과
수면시간 능력치 과
포켓몬명
파이리 5 60 문과
loc

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

python
df.loc[df['수면시간'] > 7, '능력치'] # 1개 열 가져오기
# 수면시간이 7시간 초과인 행들 중 열 이름이 능력치인 데이터 가져오기
# 결과
포켓몬명
꼬부기 80
잠만보 90
Name: 능력치, dtype: int64
df.loc[df['수면시간'] > 7, ['능력치', '과']] # 2개 열 가져오기
# 수면시간이 7시간 초과인 데이터 중 열 이름이 능력치와 과인 데이터 가져오기
# 결과
능력치 과
포켓몬명
꼬부기 80 이과
잠만보 90 문과
iloc

iloc를 사용할 수도 있습니다.

python
df.iloc[:, :2][df['수면시간'] > 7]
# 결과
수면시간 능력치
포켓몬명
꼬부기 8 80
잠만보 18 90
query

query 메서드를 사용해서 특정 조건에 해당하는 데이터를 추출할 수도 있습니다.

python
df.query('과 == "이과"') # 과가 이과인 데이터만 선택
# 또는
df.query('과 != "이과"') # 과가 이과가 아닌 데이터만 선택

조건을 외부 변수에 할당한다면 query 메서드의 변수명 앞에 @ 기호를 붙이면 됩니다.

python
condition = '이과'
df.query('과 == @condition')

먼저 특정 행을 추출한 다음 특정 변수의 값을 알고 싶다면 query() 함수와 대괄호를 조합해서 사용하면 됩니다.

python
df.query("과 == '이과'")['수면시간'] # 열 이름이 과인 데이터에서 값이 이과인 데이터들의 수면시간 데이터 추출

특정 행만 선별한 뒤 2개 이상의 열에 대한 데이터를 가져오고 싶을 때는 query() 함수와 이중 대괄호를 사용하면 됩니다.

python
df.query("과 == '이과'")[['수면시간', '능력치']] # 열 이름이 과인 데이터에서 값이 이과인 데이터들의 수면시간과 능력치 데이터 추출
groupby의 get_group

groupbyget_group 메서드를 사용해도 동일한 결과를 얻을 수 있습니다.

python
df.groupby('과').get_group('이과') # 가 이과인 데이터만 선택

groupby 함수의 사용 방법은 Python pandas 데이터 재형성, 연산, 집계하는 법을 참조해주세요. 이번에는 조건이 2개 이상인 경우를 살펴보겠습니다.

조건 2개 이상

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

그리고(AND): &

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

python
df.loc[(df['수면시간'] > 7) & (df['과'] == '이과')]
# 또는
df.query('수면시간 > 7 & 과 == "이과"')
# 결과
수면시간 능력치 과
포켓몬명
꼬부기 8 80 이과
또는(OR)
'|'

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

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

만일 여러 개의 | 기호를 사용해서 코드가 길어지면 isin 메서드를 이용해 코드 길이를 줄일 수 있습니다.

isin

isin 메서드는 특정 값에 대한 포함 여부를 불리언값으로 반환합니다.

python
result = df['과'].isin(['이과', '감자']) # '과' 열의 값으로 '이과' 또는 '감자'가 있는지를 확인
result
# 결과
포켓몬명
피카츄 True
파이리 False
꼬부기 True
잠만보 False
Name:, dtype: bool

여기서 isin 메서드를 아래와 같이 필터로 사용하면 원하는 값만을 포함한 데이터를 추출할 수 있습니다.

python
filt = df['과'].isin(['이과', '감자']) # '과'가 '이과' 또는 '감자'인 포켓몬
df[filt] # filt를 조건 필터로 사용
# 결과
수면시간 능력치 과
포켓몬명
피카츄 7 40 이과
꼬부기 8 80 이과
query + is

query()is 메서드를 사용해도 위와 동일한 결과를 얻을 수 있습니다.

python
df.query('과 in ["이과", "감자"]')
get_indexer

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)

6) 문자열: startswith, endswith, contains

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

시작: startswith

python
filt = df['과'].str.startswith('이') # '이'로 시작
df[filt]
# 결과
수면시간 능력치 과
포켓몬명
피카츄 7 40 이과
꼬부기 8 80 이과

끝: endswith

python
filt = df['과'].str.endswith('능') # 예체능에서 '능'으로 끝남
df[filt]
# 결과
없음

포함: contains

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

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

전체 데이터를 가져오려면 다음과 같이 사용하면 됩니다.

python
filt = df['과'].str.contains('문') # '문' 포함
df[filt]
# 결과
수면시간 능력치 과
포켓몬명
파이리 5 60 문과
잠만보 18 90 문과
python
filt = df['과'].str.contains('문') # '문' 포함
df[~filt] # '과'에 '문'이 들어가는 데이터 제외
# 결과
수면시간 능력치 과
포켓몬명
피카츄 7 40 이과
꼬부기 8 80 이과

만일 NaN으로 된 데이터가 있다면 na 파라미터를 이용해 해당 데이터를 제외할 수 있습니다.

python
filt = df['과'].str.contains('문', na=False) # NaN으로 된 데이터를 False로 처리
df[~filt]

7) 유일값: unique, nunique

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

종류

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

python
df['과'].unique()
# 결과
array(['이과', '문과'], dtype=object)

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

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

개수

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

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

8) 빈도수: value_counts

value_counts 메서드는 유일 범주별 빈도(frequency)를 계산하여 빈도표(frequency table)를 Series 객체로 반환해줍니다. 도수는 값의 크기에 따라 내림차순으로 정렬됩니다.

기본

python
df['과'].value_counts()
df['과']
# 결과
이과 2
문과 2
Name:, dtype: int64
python
pd.value_counts(df['과'].values, sort=False)
# 결과
이과 2
문과 2
dtype: int64

만일 인덱스를 알파벳 순으로 정렬하고 싶다면 df.value_counts()sort_index()를 사용하면 됩니다.

python
df['과'] = df['과'].value_counts().sort_index()
df['과']
# 결과
문과 2
이과 2
Name:, dtype: int64

비율

만약 각 유일값의 도수가 전체에서 차지하는 비율, 즉 상대빈도(relative frequency)를 알고 싶다면 normalize=True 옵션을 주면 됩니다.

python
df['과'].value_counts(normalize=True)
# 결과
이과 0.5
문과 0.5
Name:, dtype: float64

히스토그램

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

python
df2 = pd.DataFrame({'1분기': [5, 3, 4, 1, 2],
'2분기': [2, 3, 5, 1, 3],
'3분기': [4, 1, 5, 2, 1]})
result = df2.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

위 결과의 행 라벨(1, 2, 3, 4, 5)은 유일 범주입니다. 행 라벨은 각 열에서 해당 값이 몇 번 나타났는지 알려줍니다. apply 함수의 사용법은 Python pandas 데이터 재형성, 연산, 집계하는 법을 참조해주세요.

9) 그룹별 순서: groupby + cumcount

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

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

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

참고 문헌

...

©2023 Snug Archive. All rights reserved.

Contact me at snugarchive@gmail.com.