4. 판다스 시리즈#

판다스Pandas는 넘파이와 함께 데이터 분석에서 가장 많이 활용되는 라이브러리다. 판다스가 제공하는 두 개의 자료형 SeriesDataFrame은 데이터를 매우 효율적으로 다루는 다양한 기능을 제공한다.

넘파이 어레이는 수치형 데이터를 처리하는 데에 특화된 반면, 판다스의 시리즈와 데이터프레임은 표table 형식으로 제공되는 모든 유형의 데이터를 다룰 수 있다.

먼저 Series 객체를 소개한다.

기본 설정

numpypandas 라이브러리를 각각 nppd로 불러온다.

import numpy as np
import pandas as pd

4.1. 시리즈 생성#

시리즈는 1차원 어레이와 동일한 구조를 갖는다. 다만 인덱스를 0, 1, 2..가 아닌 원하는 값으로 지정할 수 있다. 시리즈를 생성하기 위해 리스트, 넘파이 1차원 어레이, 사전 등을 이용한다.

리스트 활용

리스트 또는 1차원 어레이를 이용하여 간단하게 시리즈를 생성할 수 있다. dtype은 어레이 항목의 자료형을 가리키는 것처럼 시리즈에 포함된 항목들의 자료형을 의미한다.

아래 코드는 리스트를 이용하여 시리즈를 생성한다. 인덱스를 별도로 지정하지 않으면 리스트, 넘파이 어레이 등에서 사용된 정수 인덱스가 사용된다.

ser1 = pd.Series([11, -4, 7, 42, -5, 20])
ser1
0    11
1    -4
2     7
3    42
4    -5
5    20
dtype: int64

시리즈 객체의 자료형은 다음과 같다.

type(ser1)
pandas.core.series.Series

어레이 활용

넘파이 1차원 어레이를 이용해 동일한 방식으로 시리즈를 생성할 수 있다.

ser1 = pd.Series(np.array([11, -4, 7, 42, -5, 20]))
ser1
0    11
1    -4
2     7
3    42
4    -5
5    20
dtype: int64

사전 활용

사전을 이용하여 시리즈를 생성할 수 있다. 사전의 키가 인덱스로 지정된다.

아래 코드는 6명의 키 (cm) 정보를 담은 시리즈를 생성한다.

info_dict = {'김강현':172.5, '황현':163.5, '남궁수현':156.7, '최흥선':187.2, '김선주':164.6, '함중아':178.3}
ser2 = pd.Series(info_dict)
ser2
김강현     172.5
황현      163.5
남궁수현    156.7
최흥선     187.2
김선주     164.6
함중아     178.3
dtype: float64

4.2. 시리즈 속성#

index 속성

index 속성은 인덱스로 사용된 값들로 구성된 Index 객체를 가리킨다. 자동으로 생성된 정수 인덱스는 range와 유사한 RangeIndex 자료형으로 지정된다.

ser1.index
RangeIndex(start=0, stop=6, step=1)

index 속성을 다른 값으로 할당하는 방식으로 새로운 인덱스를 지정할 수 있다.

new_index = ['영', '일', '이', '삼', '사', '오']
ser1.index = new_index
ser1
영    11
일    -4
이     7
삼    42
사    -5
오    20
dtype: int64

처음부터 인덱스를 지정하면서 시리즈를 생성할 수 있다.

  • index 키워드 인자: 항목의 수와 동일한 길이를 갖는 리스트여야 하고, 리스트에 포함된 순서대로 항목에 매칭된다.

ser1 = pd.Series([11, -4, 7, 42, -5, 20], index=new_index)
ser1
영    11
일    -4
이     7
삼    42
사    -5
오    20
dtype: int64
ser1.index
Index(['영', '일', '이', '삼', '사', '오'], dtype='object')

name 속성

Series 객체와 시리즈의 Index 객체 모두 name 속성에 항목과 연관된 이름을 저장할 수 있다.

아래 코드는 시리즈와 시리즈의 인덱스에 name 속성을 지정한다.

  • 시리즈 항목은 센티미터 단위의 키 정보를 담음: 시리즈 객체의 name 속성을 '키 (cm)'로 지정

  • 시리즈의 인덱스은 사람 이름으로 구성됨: 시리즈 인덱스 객체의 name 속성을 '이름'으로 지정

ser2.name = '키 (cm)'
ser2.index.name = '이름'

시리즈의 이름이 지정됨이 확인된다.

ser2
이름
김강현     172.5
황현      163.5
남궁수현    156.7
최흥선     187.2
김선주     164.6
함중아     178.3
Name: 키 (cm), dtype: float64

인덱스의 이름도 확인된다.

ser2.index
Index(['김강현', '황현', '남궁수현', '최흥선', '김선주', '함중아'], dtype='object', name='이름')

values 속성

values 속성은 시리즈의 항목만으로 구성된 1차원 어레이를 가리킨다.

ser2.values
array([172.5, 163.5, 156.7, 187.2, 164.6, 178.3])

4.3. 시리즈 인덱싱#

1차원 넘파이 어레이와 거의 동일하게 작동한다. 설명을 위해 아래 시리즈를 이용한다.

ser3 = pd.Series(np.arange(1, 3.1, 0.5), index=['A', 'B', 'C', 'D', 'E'])
ser3
A    1.0
B    1.5
C    2.0
D    2.5
E    3.0
dtype: float64

시리즈 인덱싱은 항목별로 매칭된 인덱스를 사용하면 된다.

ser3['B']
1.5

시리즈는 내부적으로 행별로 자동으로 0, 1, 2 등으로 시작하는 정수 인덱스를 지정한다. 항목에 매칭된 인덱스 대신, 아래 형식으로 정수 인덱서를 활용하여 인덱싱을 사용할 수 있다. 아래 코드는 B 인덱스가 둘째 행을 가리키기에 정수 1을 이용하여 이전 코드와 동일한 결과를 내는 인덱싱을 실행한다.

ser3.iloc[1]
1.5

반면에 인덱스 E에 해당하는 인덱싱은 다음 세 가지 방식으로 가능하다. -1은 마지막 인덱스를 가리킴에 주의한다.

ser3['E']
3.0
ser3.iloc[4]
3.0
ser3.iloc[-1]
3.0

4.4. 시리즈 슬라이싱#

행의 정수 인덱스를 이용한 슬라이싱 또한 iloc[] 객체를 이용한다. 사용법은 1차원 어레이의 경우와 유사하다.

ser3.iloc[1:3]
B    1.5
C    2.0
dtype: float64

반면에 정수가 아닌 주어진 인덱스를 이용하는 슬라이싱은 리스트의 슬라이싱과 비슷하지만, 지정된 구간의 양쪽 끝을 모두 포함한다는 점이 다르다. 3번 인덱스의 행이 D 인덱스 행에 해당하지만 아래 코드는 위 코드와 다른 결과를 낸다.

ser3['B':'D']
B    1.5
C    2.0
D    2.5
dtype: float64

슬라이싱을 이용하여 지정된 구간의 항목을 지정할 수 있다. 지정되는 항목은 하나의 값이거나 슬라이싱 구간의 크기와 동일한 리스트, 튜플, 1차원 어레이 등이 사용된다.

하나의 값이 지정되는 경우 지정된 구간의 모든 항목이 동일한 값으로 지정되며, 리스트 등이 지정되면 각각의 인덱스에 각각의 항목이 지정된다.

ser3.iloc[1:3] = 7.2
ser3
A    1.0
B    7.2
C    7.2
D    2.5
E    3.0
dtype: float64
ser3['B':'C'] = 5.0
ser3
A    1.0
B    5.0
C    5.0
D    2.5
E    3.0
dtype: float64
ser3.iloc[1:3] = [1.5, 2.0]
ser3
A    1.0
B    1.5
C    2.0
D    2.5
E    3.0
dtype: float64
ser3['B':'C'] = np.array([7.2, 5.0])
ser3
A    1.0
B    7.2
C    5.0
D    2.5
E    3.0
dtype: float64

4.5. 예제#

예제 1

아래 리스트를 이용하여 시리즈를 생성하시오. 단, np.nan은 결측치, 즉 값이 없어서 비어있는 자리를 표현하는 부동소수점 값이다.

aList = [1, 3, 5, np.nan, 6, 8]
type(np.nan)
float

답:

시리즈와 데이터프레임에서 결측치는 NaN으로 표시된다.

pd.Series(aList)
0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64

예제 2

다음 코드는 a부터 e까지 알파벳 소문자를 인덱스로 갖는 랜덤 숫자로 구성된 시리즈를 생성한다. np.random.seed() 함수는 난수 생성을 위한 시드를 지정한다. 수동으로 시드를 지정하면 난수 생성 코드를 실행할 때 항상 동일한 결과를 얻는다.

np.random.seed(42)

rand_5 = pd.Series(np.random.randn(5), index=["a", "b", "c", "d", "e"])
rand_5
a    0.496714
b   -0.138264
c    0.647689
d    1.523030
e   -0.234153
dtype: float64

아래 코드의 실행 결과를 설명해 보시오.

rand_5.reindex(["e", "b", "f", "d"])
e   -0.234153
b   -0.138264
f         NaN
d    1.523030
dtype: float64

답:

시리즈 객체의 reindex() 메서드는 기존 시리즈를 지정된 인덱스의 순서대로 정렬한다. 다만 기존 시리즈에 없는 인덱스에 대응하는 항목은 결측치 NaN으로, 기존 시리즈에 있지만 언급되지 않는 인덱스에 대응하는 항목은 무시한다. 따라서 인덱스 f의 값은 결측치로 지정되었고, 인덱스 ac 행은 무시된다.