OHSAYU 2022. 9. 6. 12:44

Series Class

    Series(시계열)는 Numpy에서 제공하는 1차원 배열과 비슷하지만 각 데이터의 의미를 표시하는 인덱스(index)를 붙일 수 있다. 데이터 자체는 값(value)라고 한다. 대부분의 데이터는 시계열(series)이나 표(table)의 형태로 나타낼 수 있다. 판다스는 이러한 데이터를 다루기 위한 시리즈(Series) 클래스와 데이터프레임(DataFrame) 클래스를 제공한다.

시리즈 = 값(value) + 인덱스(index)

Series 생성

    데이터를 리스트나 1차원 배열 형식으로 Series 클래스 생성자에 넣어주면 시리즈 클래스 객체를 만들 수 있다. 이 때 인덱스의 길이는 데이터의 길이와 같아야 한다. 다음 예에서 '서울',  '부산'등의 문자열이 인덱스의 값이다. 인덱스의 값을 인덱스 라벨(label)이라고도 한다. 인덱스 라벨은 문자열뿐 아니라 날짜, 시간, 정수 등도 가능하다. 다음 예제는 각 도시의 2015년 인구 데이터를 시리즈로 만든 것이다.

korea_population = pd.Series([9904312, 3448737, 2890451, 2466052],
                             index=['서울', '부산', '인천', '대구'])

print(korea_population)
>>> 
서울    9904312
부산    3448737
인천    2890451
대구    2466052
dtype: int64

만약 인덱스를 지정하지 않고 시리즈를 만들면 시리즈의 인덱스는 0부터 시작하는 정수 값이 된다.

pd.Series(range(10, 14))
>>> 
0    10
1    11
2    12
3    13
dtype: int64

시리즈의 인덱스는 index 속성으로 접근할 수 있다. 시리즈의 값은 1차원 배열이며 values 속성으로 접근할 수 있다. 

korea_population.index
>>> Index(['서울', '부산', '인천', '대구'], dtype='object')

korea_population.values
>>> array([9904312, 3448737, 2890451, 2466052], dtype=int64)

name 속성을 이용하여 시리즈 데이터에 이름을 붙일 수 있다. index.name 속성으로 시리즈의 인덱스에도 이름을 붙일 수 있다.

korea_population.name = '인구'
korea_population.index.name = '도시'
korea_population
>>>
도시
서울    9904312
부산    3448737
인천    2890451
대구    2466052
Name: 인구, dtype: int64

Series 연산

Numpy array처럼 Series도 벡터화 연산을 할 수 있다. 다만 연산은 시리즈의 값에만 적용되며 인덱스 값은 변하지 않는다. 예를 들어 인구 숫자를 백만 단위로 만들기 위해 시리즈 객체를 1,000,000으로 나누어도 인덱스 라벨에는 영향을 미치지 않는 것을 볼 수 있다.

korea_population / 1000000
>>>
도시
서울    9.904312
부산    3.448737
인천    2.890451
대구    2.466052
Name: 인구, dtype: float64

Series 인덱싱, 슬라이싱

Series는 Numpy Array에서 가능한 인덱스 방법 이외에도 인덱스 라벨을 이용한 인덱싱도 할 수 있다. 배열 인덱싱이나 인덱스 라벨을 이용한 슬라이싱도 가능하다. 시리즈 데이터를 인덱싱 하면 값이 나온다.

korea_population[1], korea_population['서울']
>>> (3448737, 9904312)

배열 인덱싱을 하면 부분적인 값을 가지는 시리즈 자료형을 반환한다. 자료의 순서를 바꾸거나 특정한 자료만 선택할 수 있다.

korea_population[['서울','인천']]
>>>
도시
서울    9904312
인천    2890451
Name: 인구, dtype: int64
korea_population[[1,3]]
>>>
도시
부산    3448737
대구    2466052
Name: 인구, dtype: int64
korea_population[(250e4 < korea_population) & (korea_population < 500e4)]
>>> 
도시
부산    3448737
인천    2890451
Name: 인구, dtype: int64

슬라이싱을 해도 부분적인 시리즈를 반환한다. 이때 문자열 라벨을 이용한 슬라이싱을 하는 경우에는 숫자 인덱싱과 달리 콜론(:) 기호 뒤에 오는 값도 결과에 포함되므로 주의해야 한다.

korea_population[1:3]
>>>
도시
부산    3448737
인천    2890451
Name: 인구, dtype: int64
korea_population['부산':'인천']
>>>
도시
부산    3448737
인천    2890451
Name: 인구, dtype: int64

만약 라벨 값이 영문 문자열인 경우에는 인덱스 라벨이 속성인 것처럼 온점(.)을 이용하여 해당 인덱스 값에 접근할 수도 있다.

s = pd.Series(range(3), index=['a', 'b', 'c'])
s.b
>>> 1

Series와 Dictionary 자료형

    시리즈 객체는 라벨 값에 의해 인덱싱이 가능하므로 실질적으로 인덱스 라벨 값을 키(key)로 가지는 딕셔너리 자료형과 같다고 볼 수 있다. 따라서 딕셔너리 자료형에서 가지는 딕셔너리 자료형과 같다고 볼 수 있다. 따라서 딕셔너리 자료형에서 제공하는 in 연산도 가능하고 items 메서드를 사용하면 for 루프를 통해 각 원소의 키(key)와 값(value)을 접근할 수도 있다.

'서울' in korea_population
>>> True
for k, v in korea_population.items():
    print('%s = %d' %(k,v))
>>>
서울 = 9904312
부산 = 3448737
인천 = 2890451
대구 = 2466052

또 딕셔너리 객체에서 시리즈를 만들 수도 있다. 이번에는 2010년의 인구 자료를 korea_population2라는 이름의 시리즈로 만들어 보자. 이 데이터에는 대구의 인구 자료는 없지만 대신 대전의 인구 자료가 포함되어 있다.

korea_population2 = pd.Series({"서울": 9631482, "부산": 3393191, "인천": 2632035, "대전": 1490158})
korea_population2
>>>
서울    9631482
부산    3393191
인천    2632035
대전    1490158
dtype: int64

딕셔너리의 원소는 순서를 가리지 않으므로 시리즈의 데이터도 순서가 보장되지 않는다. 만약 순서를 정하고 싶다면 인덱스를 리스트로 지정해야 한다.

korea_population2 = pd.Series({"서울": 9631482, "부산": 3393191, "인천": 2632035, "대전": 1490158},
                               index=["부산", "서울", "인천", "대전"])
korea_population2
>>>
부산    3393191
서울    9631482
인천    2632035
대전    1490158
dtype: int64

인덱스 기반 연산

이번에는 2015년도와 2010년의 인구 증가를 계산해 보자. 두 개의 시리즈의 차이를 구하면 된다. 두 시리즈에 대해 연산을 하는 경우 인덱스가 같은 데이터에 대해서만 차이를 구한다.

diff_korea_population = korea_population - korea_population2 # 인덱스가 같은 데이터끼리 연산
diff_korea_population
>>>
대구         NaN
대전         NaN
부산     55546.0
서울    272830.0
인천    258416.0
dtype: float64
korea_population.values - korea_population2.values # 인덱스에 관계없이 순서대로 연산
>>> array([ 6511121, -6182745,   258416,   975894], dtype=int64)

대구와 대전의 경우에는 2010년 자료와 2015년 자료가 모두 존재하지 않기 때문에 계산이 불가능하므로 NaN(Not a Number)이라는 값을 가지게 된다. 또한 NaN값이 float자료형에서만 가능하므로 다른 계산 결과 모두 float 자료형이 되었다는 점에 주의한다. NaN이 아닌 값을 구하려면 notnull 메서드를 사용한다.

diff_korea_population.notnull()
>>> 
대구    False
대전    False
부산     True
서울     True
인천     True
dtype: bool
diff_korea_population[diff_korea_population.notnull()]
>>>
부산     55546.0
서울    272830.0
인천    258416.0
dtype: float64

마찬가지로 인구 증가율(%)은 다음과 같이 구할 수 있다.

rate_korea_population = (korea_population - korea_population2) / korea_population2 * 100
rate_korea_population = rate_korea_population[rate_korea_population.notnull()]
rate_korea_population
>>>
부산    1.636984
서울    2.832690
인천    9.818107
dtype: float64

데이터의 갱신, 추가, 삭제

인덱싱을 이용하면 딕셔너리처럼 데이터를 갱신(update)하거나 추가(add)할 수 있다.

rate_korea_population['부산'] = 1.63
rate_korea_population
>>>
부산    1.630000
서울    2.832690
인천    9.818107
dtype: float64

데이터를 삭제할 때도 딕셔너리처럼 del 명령을 사용한다.

del rate_korea_population['서울']
rate_korea_population
>>>
부산    1.630000
인천    9.818107
dtype: float64

 

 

출처 : https://datascienceschool.net/01%20python/04.01%20%ED%8C%90%EB%8B%A4%EC%8A%A4%20%ED%8C%A8%ED%82%A4%EC%A7%80%EC%9D%98%20%EC%86%8C%EA%B0%9C.html

 

4.1 판다스 패키지의 소개 — 데이터 사이언스 스쿨

.ipynb .pdf to have style consistency -->

datascienceschool.net