데이터/데이터 분석

파이썬 판다스 (시리즈/데이터프레임/인덱싱/멀티인덱싱)

Jerry_K 2023. 8. 22. 20:16

이번 글은 이수안님 판다스 강의 정리  (예전에 정리한건데 게을러서 이제 정리...)

https://www.youtube.com/watch?v=lG8pEwvYwCw 


언제나 그렇듯 기본 라이브러리 호출

import numpy as np
import pandas as pd

Series(시리즈)

[1] 시리즈 기본

시리즈는 데이터 구조 중 하나로, 1차원 배열 형태의 데이트를 나타내는 객체

=>  이것들이 모이면 데이터 프레임(Data frame)이 된다

a = pd.Series([1,2,3,4,5])
a

a.values, a.index

 

값은 1~5이고 인덱스는 0~4

 

[2] 시리즈 인덱스 바꾸기

b = pd.Series([1,2,3,4,5], index=["a","b","c","d","e"])
b

b의 인덱스는 "a"~"e"까지 변경 됨


DataFrame(데이터프레임)

pd.DataFrame(np.random.rand(5,5),
            index = [1,2,3,4,5],
            columns=["a","b","c","d","e"])

(np.random.rand(5,5)로 0부터 1사이 균일 분포에서 무작위 실수 값 생성)

만들려는거는 데이터 프레임이니까 인덱스와 달리 컬럼(column)의 이름도 설정 가능

 

[1] 데이터셋 만들기

pop_tuple = {'서울 특별시': 9708460,
            '인천 광역시' : 3404424,
            '부산 광역시' : 2947217,
            '대구 광역시' : 2427954,
            '대전 광역시' : 1471040,
            '광주 광역시' : 1455048}
            
 male_tuple = {'서울 특별시': 4758460,
            '인천 광역시' : 1668424,
            '부산 광역시' : 1437217,
            '대구 광역시' : 1199854,
            '대전 광역시' : 713040,
            '광주 광역시' : 755048}

female_tuple = {'서울 특별시': 4908460,
            '인천 광역시' : 1784424,
            '부산 광역시' : 1337217,
            '대구 광역시' : 1259854,
            '대전 광역시' : 735740,
korea_df = pd.DataFrame({"인구수" : pop_tuple,
              "남자 인구수" : male_tuple,
             "여자 인구수" : female_tuple})
korea_df

딕셔너리 값들이 세로로 정렬되어 데이터 프레임 생성


인덱싱(Indexing)

[1] 인덱스 객체

인덱스 참고

idx = pd.Index([2,3,4,5])
print("idx :", idx)
print("idx size :",idx.size)
print("idx shape :",idx.shape)
print("idx ndim :",idx.ndim)
print("idx dtype :",idx.dtype)

[2] 시리즈 인덱싱

a = pd.Series([0,0.25,0.5,0.75,1],
             index = ['a','b','c','d','e'])

a['f'] = 1.25
a

a[(a>0.4) & (a< 0.6)]

이런식으로도 가능

 

[3] 데이터 프레임 인덱싱

korea_df["남여비율"] = (korea_df["남자 인구수"]* 100 / korea_df["여자 인구수"])
korea_df

아까 만들어 둔 korea_df에 "남여비율" 컬럼 추가

 

 

Q. 서울 특별시부터 대전 광역시 까지 데이터를 가져오는 코드는 ?

A.

korea_df.loc["서울 특별시":"대전 광역시"]

 

Q. 2500000명 이상 되는 지역을 출력하는 코드는 ?

A. 

korea_df[korea_df["인구수"] > 2500000]

 

[4] loc / iloc로 인덱싱

korea_df.loc[:,["남자 인구수","여자 인구수"]]

loc 인덱싱은 해당 행 또는 열 이름 그대로

korea_df.iloc[:,1:3]

iloc는 해당 행 또는 열의 인덱스 위치를 쓰면 된다 (소괄호가 아니라 대괄호 주의! )


Multi Indexing(멀티 인덱싱)

여기서부터는 그냥 그 때 마다 참조하시죠!

[1] 시리즈 멀티 인덱싱

idx_tuples = [("서울 특별시", 2010), ("서울 특별시", 2020),
             ("인천 광역시", 2010), ("인천 광역시", 2020),
             ("부산 광역시", 2010), ("부산 광역시", 2020),
             ("대구 광역시", 2010), ("대구 광역시", 2020),
             ("대전 광역시", 2010), ("대전 광역시", 2020),
             ("광주 광역시", 2010), ("광주 광역시", 2020)]
             
pop_tuples = [10312434, 9720846,
             3568940 , 4539334,
             2758296, 2947217,
             2511676, 2427954,
             1503664, 1471040,
             1454636, 1455048]

idx_tuples는 튜플들의 리스트 (멀티 인덱싱을 위해)

idx = pd.MultiIndex.from_tuples(idx_tuples)

population =  pd.Series(pop_tuples, idx)

MultiIndex.from_tuples는 튜플들의 인덱스를 다중 인덱스로 만든다.

그리고 population에 넣으면 멀티 인덱스를 가진 시리즈 생성 ! 

 

Q. 광주 광역시 2020년 데이터를 출력하는 코드는 ?

population["광주 광역시",2020]

 

A. 

[1-1] 시리즈 unstack / stack

korea_mdf = population.unstack()
korea_mdf

저런 멀티 인덱스를 unstack 하면 stack 형태로 쌓인다.

korea_mdf = korea_mdf.stack()
korea_mdf

stack 하려면 stack 함수를 ... 

 

[1-2] 다중 인덱스 시리즈를 데이터 프레임으로 변환

male_tuples = [5111259,4732275,
             1773170,1668618,
             1390356, 1476813,
             1255245, 1198815,
             753648, 734441,
             721780, 720060]
             
female_tuples = [5201286,4988571,
                1794740, 1735805,
                1367950,1470404,
                1256431,1229139,
                750016,736599,
                732856,734988]

korea_mdf = pd.DataFrame({"총인구수":population, "남자인구수":male_tuples,"여자인구수":female_tuples })

(population은 앞에 코드 사용)

 

[3] 다중 인덱스 생성

pd.DataFrame(np.random.rand(18).reshape(6,3), 
             index= [["a","a","b","b","c","c"],[1,2,1,2,1,2]],
            columns = ["c1","c2","c3"])

(간단한거는 MultiIndex.from_~ 를 쓰는 것보다 이게 편한 듯 보인다.)

pd.MultiIndex.from_arrays([['a','a','b','b','c','c'],[1,2,1,2,1,2]])

pd.MultiIndex.from_tuples([('a',1),('a',2),('b',1),('b',2),('c',1),('c',2)])

pd.MultiIndex.from_product([['a','b','c'],[1,2]])

위에 다중 인덱스를 MultiIndex.from_~를 통해 생성하는건데 배열,튜플에 따라 다르고, 그냥 곱으로도 만들 수 있다.

 

[3-1] 다중 인덱스에 name 주기

a = pd.DataFrame(np.random.rand(18).reshape(6,3), 
             index= [["a","a","b","b","c","c"],[1,2,1,2,1,2]],
            columns = ["c1","c2","c3"],)
a.index.names = ["index1","index2"]
a.columns.names = ["column1"]
a

이런식으로 column과 index에 name을 줄 수 있다.  만일 column이 다중 인덱스면 pd.columns.names에 한개 더 추가 하면 된다. ( 멀티 컬럼 만드는 것은 멀티 인덱스 만드는거랑 같음) 

* name이 아니라 names 이다.

 

col = pd.MultiIndex.from_product([["c1","c2","c3"],[1,2]], names = ["col_name1", "col_name2"])
idx = pd.MultiIndex.from_product([['a','b','c'],[1,2]], names = ["names1", "names2"])
data = np.round(np.random.rand(6,6),2)

mdf = pd.DataFrame(data, columns=col, index=idx)
mdf

 

이렇게 깔끔하게도 줄 수 있다.

 

[4] 다중 인덱스에 인덱싱

mdf["c1"][1]

이렇게 인덱싱 가능하다 . 좀 더 구체적으로 살펴보자

 

Q.  name1 : "b" , name2 : 2 행에서  col_name1 : "c2", col_name2 : 2 의 값 0.52를 출력하는 코드는 ?

A.

mdf.loc[('b', 2),("c2",2)]

(np.random 함수로 뽑은 데이터 프레임이므로 값들이 다를것이다)

 

mdf.iloc[3,3]

iloc로하면 그냥 0 기준 위치 넣으면 된다.

 

[5] 인덱스 슬라이싱

idx_slice = pd.IndexSlice
mdf.loc[idx_slice[:,1],idx_slice["c1",:]]

이런식으로 원하는 조건만 출력 가능하다. 근데 이게 좀 헷갈리니까 간단한거는 아래 방법도 좋을 듯

mdf.loc[(["a","b","c"],[1,1,1]),(["c1","c1"],[1,2])]

 

[6] 다중 인덱스 재정렬

위에서 사용한 korea_mdf 데이터를 사용해보자.

korea_mdf = korea_mdf.sort_index(axis=1,ascending=True)
korea_mdf

sort_index로 정렬을 했다. 

파라미터들은 axis는 축으로 1이면 column기준 (0은 row 기준)이고 ascending = True 는 오름차순으로 하겠다는 의미

따라서 위의 데이터 프레임으로 재 정렬된다.

 

 

[6-1] 인덱스 초기화

korea_mdf.reset_index()

간단하게 index 초기화


Pandas(Series_Dataframe_Indexing)_이수안.ipynb
0.13MB