pandas-series
pandas Series 객체

pandas(판다스)는 파이썬의 데이터 분석 라이브러리입니다. pandas는 데이터를 간편하게 처리할 수 있도록 도와줍니다. 엑셀에서 데이터를 행과 열로 다루는 것과 같은 방식으로 말입니다. 엑셀과 같은 좋은 도구가 있는데 pandas를 사용하면 좋은 이유는 무엇일까요?

pandas는 빅데이터(big data)처럼 처리할 데이터의 양이 많을 때 사용하기 좋습니다. 엑셀에서는 대용량의 데이터를 처리하면 프로그램의 속도가 느려집니다. 데이터를 감당하지 못하고 과부하가 생기는 것입니다. 반면, pandas는 많은 양의 데이터를 처리하더라도 영향을 받지 않습니다. 오히려 대용량의 데이터를 처리하기에 적합합니다. pandas와 엑셀을 사용 목적에 맞게 적절히 활용한다면 데이터 분석을 더 효율적으로 할 수 있을 것입니다.

pandas에는 세 가지 자료구조(data structure)가 있습니다. Series(시리즈), DataFrame(데이터 프레임), 그리고 Panel(패널)입니다. Series는 1차원 데이터 자료구조이고, DataFrame은 2차원, Panel은 3차원 데이터 자료구조입니다. 이번 시간에는 Series 사용법을 알아보겠습니다.

설치 및 환경설정

Series 사용법을 알아보기 전에 먼저 실습 환경을 준비하겠습니다.

실습 환경

글에서는 실습 환경으로 주피터 노트북(Jupyter Notebook)을 사용했습니다. 주피터 노트북을 사용하시는 경우 해당 코드를 실행하시고 만들어진 변수를 한 번 더 입력하셔야 결과를 보실 수 있습니다. 예를 들어 "myObject"라는 변수를 만드셨다면 "myObject"를 한 번 더 입력하셔야 결괏값이 출력됩니다.

python
myObject = pd.Series([1, 2, 3])
myObject

텍스트 에디터나 IDE를 사용하시는 분들은 print() 함수를 사용하시면 됩니다. 그럼 이제 패키지를 설치해보겠습니다.

패키지 다운로드

필요한 패키지는 pandas, numpy(넘파이) 입니다. numpy는 수치 자료를 다루는데 특화된 라이브러리입니다. numpy는 pandas로 자료 분석을 할 때 함께 자주 쓰입니다. 그럼 pandas와 numpy를 설치해보겠습니다. 코드는 다음과 같습니다.

python
pip install pandas
pip install numpy

그럼 설치한 패키지를 가져와보겠습니다.

패키지 임포트

아래와 같이 라이브러리를 임포트해주세요.

python
import pandas as pd # pandas import
import numpy as np # numpy import

보통 pandas 패키지를 임포트 할 때 pandas를 pd, numpy 패키지를 임포트할 때는 np라고 표기합니다. 여기에서도 모든 코드 예제에서 pandas를 pd, numpy를 np로 임포트했다는 것을 가정합니다.

정의

Series는 1차원 데이터 객체입니다. 여기서 차원이란 변수의 수이고, 데이터 객체란 데이터를 담고 있는 그릇과도 같습니다. 물리적 공간에서 차원이 높아질수록 점, 선, 면을 표현하기 위한 축의 개수가 더 많아지듯, 데이터 공간에서도 차원이 높아질수록 자료구조가 더 많은 데이터 층위(layer)를 갖습니다.

Series를 자료구조와 비교하자면 Series는 키(key)에 대응하는 값(value)이 1개인 딕셔너리(dictionary)와도 같습니다. Series에서 인덱스-값의 관계는 딕셔너리에서 키-값의 관계에 대응합니다. Series에 변수의 수가 추가되면 DataFrame이 됩니다. 벡터(vector) 관점에서 보면 Series는 1차원 벡터 데이터(A = [1, 5, 3, 4])에 행 인덱스(row index)를 붙인 것이기도 합니다. 요약하자면 Series는 변수의 수가 1개인 자료구조, 열이 1개인 DataFrame입니다.

Series와 DataFrame의 차이
Series와 DataFrame의 차이  - Snug Archive
벡터(vector)
크기와 방향을 모두 가지는 어떤 양

그럼 먼저 Series를 만드는 법부터 알아보겠습니다.

생성하기(Creating)

Series를 만드는 함수는 pd.Series()입니다. 코드는 다음과 같습니다.

python
ser = pd.Series()
ser
# 결과
Series([], dtype: float64)

Series 객체를 만들려면 pd.Series 클래스에 원하는 자료구조를 인자(argument)로 주면 됩니다. 사용할 수 있는 자료구조는 다음과 같습니다.

  • 1차원 배열(array)
  • 1차원 리스트(list)
  • 딕셔너리(dictionary)
  • 튜플(tuple)

1) 1차원 배열

먼저 1차원 배열로 Series 객체를 만들어보겠습니다. 예시 코드는 다음과 같습니다.

python
data_arr = np.arange(5) # 0부터 4까지의 정수를 원소로 갖는 1차원 배열 생성
ser = pd.Series(data_arr)
ser
# 결과
0 0
1 1
2 2
3 3
4 4
dtype: int32

2) 1차원 리스트

python
data_ls = pd.Series([100, 50, 70, 90])
ser1 = pd.Series(data_ls)
ser1
# 결과
0 100
1 50
2 70
3 90
dtype: int64
python
data_ls = range(5, 11) # 5부터 10까지의 정수가 담긴 리스트 만들기
ser2 = pd.Series(data_ls)
ser2
# 결과
0 5
1 6
2 7
3 8
4 9
5 10
dtype: int64

3) 딕셔너리

Series를 만드는 세 번째 방법은 딕셔너리를 이용하는 것입니다. Series의 정의에서 언급했던 것처럼 Series는 길이가 고정되어 있으며 알파벳 순으로 정렬된 사전형 자료구조와 비슷합니다.

python
data_dict = {'국어': 100, '수학': 50, '영어': 70, '과학': 90} # 딕셔너리
ser = pd.Series(data_dict)
ser
# 결과
국어 100
수학 50
영어 70
과학 90
dtype: int64

4) 튜플

튜플로 Series 객체를 만드는 방식은 리스트로 Series를 만드는 방식과 동일합니다.

python
data_tuples = ([100, 50, 70, 90])
ser = pd.Series(data_tuples)
ser
# 결과
0 100
1 50
2 70
3 90
dtype: int64

지금까지 4가지 자료구조(1차원 배열, 1차원 리스트, 딕셔너리, 튜플)를 이용해 Series를 생성하는 법을 살펴보았습니다. 그럼 우리가 만든 Series 객체에는 어떻게 접근할 수 있을까요? Series의 개별 원소에 접근하려면 색인(index)이 필요합니다. 색인이란 무엇일까요?

색인 관리하기(Managing index)

색인이란 데이터의 주소(address)와도 같은 것입니다. 각 값에는 데이터의 주소가 있고 우리는 이 주소를 가지고 데이터에 접근할 수 있죠.

색인은 Series 객체를 만들 때 기본적으로 만들어집니다. 코드를 실행했을 때 Series의 가장 왼쪽 편에 있는 정수(integer)가 색인입니다.

python
# 예시
0 100
1 50
2 70
3 90
dtype: int64

정수로 이루어져 있다고 해서 정수 색인(integer index)이라고도 합니다. 색인 관리하기에서는 색인을 지정하고, 확인 및 변경하는 법을 살펴보겠습니다.

지정하기

행 색인

개별 원소의 색인을 지정하려면 pandas.Series 클래스의 index 매개변수를 이용하면 됩니다. 예시 코드는 다음과 같습니다.

python
data = np.arange(5)
ser = pd.Series(data, index=[x for x in 'abcde']) # 인덱스 지정: ['a', 'b', 'c', 'd', 'e']
ser
# 결과
a 0
b 1
c 2
d 3
e 4
dtype: int32

통합 색인

통합 색인명을 부여하려면 pandas.Series.index.name 속성을 사용하면 됩니다.

python
data = {'국어': 100, '수학': 50, '영어': 70, '과학': 90}
new_index = ['국어', '수학', '영어', '사회']
ser = pd.Series(data, index=new_index)
ser.index.name = '과목명' # 통합 색인명 부여
ser
# 결과
과목명
국어 100.0
수학 50.0
영어 70.0
사회 NaN
dtype: float64

확인하기

색인은 pandas.Series.index 속성으로 확인할 수 있습니다.

python
data_dict = {'국어': 100, '수학': 50, '영어': 70, '과학': 90} # 딕셔너리
ser = pd.Series(data_dict)
ser.index # ser의 색인 가져오기
# 결과
Index(['국어', '수학', '영어', '과학'], dtype='object')
특정 Series 객체에 해당 색인이 있는지 확인하려면 원하는 색인 라벨(label)을 넣으면 됩니다.
```python
'감자' in ser # ser에 '감자'라는 색인이 있는지 확인
# 결과
False

변경하기

만일 기존 색인을 새로운 색인으로 바꾸고 싶다면 Series의 pandas.index 속성에 새 색인명이 담긴 자료구조를 넘겨주면 됩니다.

python
ser = pd.Series([1, 2, 3, 4, 5])
ser.index = [f'{x + 1}번' for x in range(4)] # ['1번', '2번', '3번', '4번', '5번']
# 결과
10
21
32
43
54
dtype: int32

기존 색인을 새로운 색인으로 대체할 때 기존 색인에 대응하는 새로운 색인이 없으면 새로운 색인에 해당하는 값은 NaN으로 표시됩니다. NaNNot a Number를 뜻합니다. 데이터값에 맵핑(mapping)되었던 기존 색인이 없어졌기 때문에 가져올 값도 없어진 것입니다.

python
data = {'국어': 100, '수학': 50, '영어': 70, '과학': 90}
new_index = ['국어', '수학', '영어', '사회']
ser2 = pd.Series(data, index=new_index)
ser2
# 결과
국어 100.0
수학 50.0
영어 70.0
사회 NaN
dtype: float64

객체 정보 수정하기

데이터 객체에 이름을 붙이려면 pandas.Series.name 옵션을 사용하면 됩니다.

python
ser2.name = '과목점수' # 데이터 객체에 이름 지정
# 결과
국어 100.0
수학 50.0
영어 70.0
사회 NaN
Name: 과목점수, dtype: float64

지금까지 우리는 Series 객체를 생성하고 객체의 색인과 정보를 관리하는 법을 알아보았습니다. 데이터를 만들지 않고 다른 곳에서 가져올 수도 있습니다. 데이터를 가져오는 법은 DataFrame편에서 자세히 다루겠습니다. 자세한 사항을 알고 싶은 분들은 Python pandas 데이터 생성, 로딩과 저장, 색인 관리하는 법에서 "로딩과 저장"을 참조해주세요.

읽기(Reading)

확인하기

개요

전체 데이터는 pandas.Series.head()를 통해 확인합니다.

python
data = np.arange(10)
ser = pd.Series(data)
ser.head(3) # 처음부터 총 3개행만 가져오기

이밖에도 아래와 같은 옵션이 있습니다.

  • Series.tail(): Series 끝에서부터 기본 5개 행 가져오기
  • Series.shape: Series의 행 개수를 알고
  • Series.describe(): 수치 자료의 요약 통계량 확인하기

전체 값은 pandas.Series.values 속성으로 가져올 수 있습니다.

python
ser.values
# 결과
array([100, 50, 70, 90], dtype=int64)

결측치

Series에서 누락된 데이터를 찾을 때는 isnull 함수나 notnull 함수를 사용하면 됩니다.

python
pd.isnull(ser2) # 누락된 데이터가 있는가?
# 결과
국어 False
수학 False
영어 False
사회 True
dtype: bool
pd.notnull(ser2) # 누락된 데이터가 없는가?
# 결과
국어 True
수학 True
영어 True
사회 False
dtype: bool

이 메서드는 아래 코드에서와 같이 Series의 인스턴스 메서드(methods)로도 사용할 수 있습니다.

python
ser2.isnull() # 누락된 데이터가 있는가?
# 결과
국어 False
수학 False
영어 False
사회 True
dtype: bool
ser2.notnull() # 누락된 데이터가 없는가?
# 결과
국어 True
수학 True
영어 True
사회 False
dtype: bool

지금까지 데이터를 생성하고 확인하는 법을 알아보았습니다. 그럼 이제 데이터에 접근할 수 있어야겠죠. 데이터에 접근하는 것은 데이터를 선택하는 일이기도 합니다. 여기서 특정 위치나 1개 색인 값에 매핑된 특정 값 1개를 선택하는 것을 인덱싱(indexing), 여러 개의 색인에 따라 다수의 원소로 이루어진 부분 집합을 가져오는 것을 슬라이싱(slicing)이라고 합니다.

접근하기

색인에 접근하는 방법은 파이썬의 인덱스에 접근하는 방법과 같습니다.

python
data = [1, 2, 3, 4]
ser = pd.Series(data)
ser[0] # Series의 첫 번째 원소 읽기
ser[1] # Series의 두 번째 원소 읽기
ser[:] # Series의 모든 색인 및 값 읽기
# 결과
1
2
0 1
1 2
2 3
3 4

선택하기

데이터를 선택하는 기본 방법으로는 특정 값 선택하기와 여러 색인에 해당하는 값 선택하기가 있습니다. 하나씩 살펴보도록 하죠.

1) 특정 값 1개 선택하기

특정 값을 선택하려면 색인을 사용하면 됩니다. 인덱싱할 때 정수 색인을 사용할 수도 있고 라벨 색인을 사용할 수도 있죠.

python
ser[1] # 정수 색인 사용해 Series 두 번째 원소에 접근하기
# 결과
50
ser['수학'] # 라벨 색인 사용해 Series '수학' 색인 값에 매핑된 데이터 값 가져오기
# 결과
50

2) 여러 색인에 해당하는 값 선택하기

특정 값이 아니라 여러 색인 값에 각각 맵핑된 값을 선택하려면 아래 코드에서처럼 정수 색인 리스트 또는 색인의 범위를 전달할 수 있습니다.

python
# data = {'국어': 100, '수학': 50, '영어': 70, '과학': 90}
# ser = pd.Series(data)
ser[[0, 1, 2]] # 자료 순서 그대로 출력
# 결과
국어 100
수학 50
영어 70
dtype: int64
python
ser[[2, 0, 1]] # 자료 순서 바꿔서 출력
# 결과
영어 70
국어 100
수학 50
dtype: int64
python
ser[0:2] # 정수 색인 범위 전달
# 결과
국어 100
수학 50
dtype: int64

색인을 지정했으면 색인 라벨로도 데이터를 선택할 수 있습니다.

python
ser[['국어', '수학']]
# 결과
국어 100
수학 50
dtype: int64
python
ser['국어': '영어']
# 결과
국어 100
수학 50
영어 70
dtype: int64

지금까지 인덱싱과 슬라이싱을 통해 데이터를 선택하는 법을 알아보았습니다. 만약 색인과 값을 모두 선택하려면 아래 파이썬의 함수를 사용해도 됩니다. 여기에서는 items() 함수를 사용해보았습니다.

python
for key, value in ser.items():
print(f"{key} 점수: {value}")
# 결과
국어 점수: 100
수학 점수: 50
영어 점수: 70
과학 점수: 90

3) 라벨 색인로 데이터 선택: .loc 속성 사용

pandas.Series.loc 속성에 라벨 색인을 넣으면 해당 색인에 매핑된 값을 찾을 수 있습니다.

python
ser.loc['수학'] # '수학'이라는 라벨 색인에 맵핑된 값 찾기
# 결과
50

4) 정수 색인으로 데이터 선택: .iloc 속성 사용

pandas.Series.iloc 속성은 정수 색인으로 데이터를 선택하는 방법입니다. .iloc 속성에 원하는 정수 색인을 넣으면 해당 인덱스와 연결된 값을 선택할 수 있습니다.

python
ser.iloc[1]
# 결과
50

5) 조건으로 데이터 선택

Series 객체에서는 특정 조건에 따라 원하는 데이터를 추출할 수 있습니다. 다음 코드로는 우리가 만든 Series 객체에서 75를 넘는 데이터 결과만 가져올 수 있습니다.

python
ser[ser > 75]
# 결과
국어 100
과학 90
dtype: int64

조건을 두 가지 이상으로 줄 수도 있죠. 아래 코드는 65점 초과 90점 미만인 결과를 반환합니다.

python
ser[(ser > 65) & (ser < 90)]
# 결과
영어 70
dtype: int64

지금까지 데이터를 선택하는 기본 방법과 목적별로 사용할 수 있는 방법을 알아보았습니다. 다음으로는 데이터를 추가, 수정, 삭제하는 법을 알아보겠습니다.

업데이트하기(Updating)

1) 추가하기

데이터를 추가하려면 새로운 색인과 값을 만들면 됩니다. 아래 코드는 Series 객체에 색인으로는 '음악' 과목을 값으로는 80을 추가하는 예제입니다.

python
# ser = pd.Series([100, 50, 70, 90], index=['국어', '수학', '영어', '과학'])
ser['음악'] = 80
# 결과
국어 100
수학 50
영어 70
과학 90
음악 80 # 음악 과목 추가됨
dtype: int64

2) 변경/수정/갱신하기

데이터를 수정하려면 기존의 색인명에 새 값을 부여하면 됩니다. 그럼 기존의 값이 새 값으로 갱신됩니다.

python
ser['수학'] = 100
# 또는
ser.loc['수학'] = 100
# 결과
국어 100
수학 100 # 50점에서 100으로 변경됨
영어 70
과학 90
dtype: int64

3) 연산하기

Series에서는 아주 간단하게 모든 값에 동시에 연산을 수행할 수 있습니다. 다음은 Series 객체의 모든 값을 2로 나누는 연산입니다.

python
ser / 2
# 결과
국어 50.0 # 100에서 50
수학 25.0 # 50에서 25
영어 35.0 # 70에서 35
과학 45.0 # 90에서 45
dtype: float64

Series 객체와 Series 객체끼리의 연산도 가능합니다. 산술 연산 시에는 Series가 색인과 라벨로 자동 정렬됩니다.

python
ser1 + ser2
# 결과
과학 NaN
국어 200.0
사회 NaN
수학 100.0
영어 140.0
dtype: float64
ser1.values + ser2.values
# 결과
array([200., 100., 140., nan])

삭제하기(Deleting)

데이터를 삭제하려면 del을 사용하면 됩니다.

python
del ser['국어']
# 결과
수학 100
영어 70
과학 90
dtype: int64

지금까지 데이터를 생성하는 법, 데이터에 대한 정보를 생성하는 법(데이터 이름 및 통합 색인 이름 지정), 데이터를 확인하는 방법, 데이터를 선택하는 기본 방법과 목적별로 선택하는 방법, 데이터를 추가, 수정, 삭제하는 법, 마지막으로 데이터의 연산을 살펴보았습니다.

다음 시간에는 DataFrame을 사용하는 법을 알아보겠습니다. DataFrame 사용법은 총 네 부분으로 나뉩니다.

파이썬 pandas의 Series 객체와 관련해 더 많은 내용은 pandas 공식 홈페이지 Series에서 확인하실 수 있습니다. 모두 수고 많으셨습니다.

참고 문헌

...

©2023 Snug Archive. All rights reserved.

Contact me at snugarchive@gmail.com.