본문 바로가기

Programming Language/Python_library

파이썬_활용단계 ep.2 pandas를 써서 표 안의 원하는 것만 골라뽑기

320x100

 

인덱싱과 슬라이싱은 원하는 것만 골라 뽑는 인형뽑기 게임이라고 생각하는 건 어떨까요?

불필요한 것은 버리고 필요한 것만 싹 골라가는 능력은 중요합니다.

 

서론

 

※ 주의

 

다소 반복적인 내용이 소개될 수 있습니다😂

다만 추후에 데이터 전처리나 다듬는 단계에서 기본기처럼 사용될 수 있으니

확실하게 알고 넘어가는 것이 중요할 것입니다!

🤷‍♀️

 

다시 시리즈부터 확인해보겠습니다.

 

Series

 

지난번에 시리즈는 인덱스 vs 값들의 리스트이 붙은 것임을 확인했었죠?

다시 한번 예시를 만들어보겠습니다.

 

world_cup = pd.Series([1, 2, 3, 4],  
              index=["프랑스", "아르헨티나", "크로아티아", "우루과이"])
world_cup
프랑스      1
아르헨티나    2
크로아티아    3
우루과이     4
dtype: int64

 

이렇게 인덱스와 값들이 아래로 주르륵 생성됩니다.

여기서 간단하게 데이터나 인덱스를 호출하는 방법들이 있습니다.

 

시리즈 인덱싱 (indexing)

 

series도 numpy 배열에서 가능한 인덱스 방법과 인덱스 라벨을 이용한

인덱싱도 할 수 있습니다.

 

위의 시리즈로 몇가지 호출해 보겠습니다.

 

 

* 1번째 데이터를 호출

 

world_cup[1]
2

 

* '프랑스' 인덱스 라벨을 가진 데이터를 호출

 

world_cup['프랑스']
1

 

* 리스트를 사용해서 동시에 3개 호출

world_cup[[0,3,1]]
프랑스      1
우루과이     4
아르헨티나    2
dtype: int64

 

* 인덱스를 직접 호출 - 3개입니다

world_cup[['우루과이','아르헨티나','크로아티아']]
우루과이     4
아르헨티나    2
크로아티아    3
dtype: int64

 

* 비교 연산자를 통해 인덱스 라벨을 호출

 

world_cup[(world_cup < 2)]
프랑스    1
dtype: int64

 

Series slicing

 

슬라이싱도 물론 가능합니다.

배열을 슬라이싱하면 배열이 나오고, 시리즈를 슬라이싱하면 시리즈가 나온다는 점

당연한 것이겠지요💯

숫자 인덱싱부터 보겠습니다!

 

world_cup[1:3]
아르헨티나    2
크로아티아    3
dtype: int64

 

특히, 문자열 라벨을 이용한 슬라이싱을 하는 경우 숫자 인덱싱과 달리

: 콜론 뒤에 오는 값도 결과에 포함된답니다.

 

world_cup['아르헨티나':'크로아티아']
아르헨티나    2
크로아티아    3
dtype: int64

 

* 몇몇 특수문자나 예약어를 건드리지 않으면, 문자열로 

"."을 통해 인덱스 값에 접근할 수 있습니다. 그저 속성처럼요!

 

world_cup.프랑스, world_cup.우루과이
(1, 4)

 

데이터프레임 전치

 

데이터프레임은 지난번에도 2차원 배열 데이터와 행방향 인덱스+열방향 인덱스를

합친 것이라고 보았습니다.

임의의 데이터로 다시 한번 생성해볼까요?

 

data = {
    "희귀병 환자 수": ["a질환", "b질환", "c증후군", "d증후군"],
    '2001': [1, 2, 3, 4],
    "2002": [10, 100, 1000, 1000],
    "2003": [976, 3547, 2580, 246],
    "2004": [92, 337, 2438, 2490],
    "2001-2004 증가율": [0.028, 0.013, 0.082, 0.011]}
columns = ["희귀병 환자 수", "2001", "2002", "2003", "2004", "2001-2004 증가율"] 
index = ["췌장", "지방대사", "DNA", "뇌"]
b = pd.DataFrame(data, index=index, columns=columns)
b

 

인덱스 라벨 확인

 

b.values
array([['a질환', 1, 10, 976, 92, 0.028],
       ['b질환', 2, 100, 3547, 337, 0.013],
       ['c증후군', 3, 1000, 2580, 2438, 0.082],
       ['d증후군', 4, 1000, 246, 2490, 0.011]], dtype=object)

 

데이터프레임은 행 인덱스와 열 인덱스를 뒤바꾸는,

일종의 '전치' 기능이 가능합니다.

 

전치 행렬 : 행과 열을 교환하여 얻는 행렬
행과 열을 뒤바꿔보세요!

 

먼저, numpy에서 행렬(2차원 배열)을 만들고

행 열을 바꾸는 방법은 아래와 같았습니다.

 

arr = np.arange(10).reshape(5, 2)
arr, arr.shape
(array([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]]), (5, 2))

 

b 데이터프레임의 형태를 보면 다음과 같습니다.

 

b.shape
(4, 6)

 

이를 전치하는 것은 단순합니다.

속성처럼 뒤에 .T를 붙여줍니다.

(transposed)

 

원래 데이터프레임

 

 

전치시킨 데이터프레임

 

b.T

 

좋습니다.

이제는 열 인덱싱을 진행해보겠습니다.

 

 

데이터프레임의 열 indexing

 

데이터프레임의 인덱싱은 열 라벨(column label)을 키값으로 생각하여

시작할 수 있습니다.

라벨값을 하나만 넣으면 시리즈 객체가 되고, 다수의 라벨(배열or리스트)을 넣으면

부분적인 데이터프레임이 됩니다!

 

데이터프레임 소환

 

data = {
    "2015": [9904312, 3448737, 2890451, 2466052],
    "2010": [9631482, 3393191, 2632035, 2431774],
    "2005": [9762546, 3512547, 2517680, 2456016],
    "2000": [9853972, 3655437, 2466338, 2473990],
    "지역": ["수도권", "경상권", "수도권", "경상권"],
    "2010-2015 증가율": [0.0283, 0.0163, 0.0982, 0.0141]
}
columns = ["지역", "2015", "2010", "2005", "2000", "2010-2015 증가율"]
index = ["서울", "부산", "인천", "대구"]
df = pd.DataFrame(data, index=index, columns=columns)
df

 

라벨값 하나만 넣어서 인덱싱

 

df['지역']
서울    수도권
부산    경상권
인천    수도권
대구    경상권
Name: 지역, dtype: object

 

자 이렇게, 시리즈가 되었습니다.

type 확인

 

type(df['지역'])
pandas.core.series.Series

 

* 아래처럼, 데이터프레임을 유지할 수도 있습니다.

 

df[['지역']]

바로 열라벨에 []를 씌워서 두 번 씌우는 것이죠.

 

자 위에서 처럼, 데이터프레임의 열 인덱스가 문자열 라벨을 가지고 있는 경우,

숫자를 나타내는 정수 인덱스를 열 인덱싱에 사용할 수 없습니다.

 

(오류 사례)

df[['1']]
   1372                 if use_interval_msg:
   1373                     key = list(key)
-> 1374                 raise KeyError(f"None of [{key}] are in the [{axis_name}]")
   1375 
   1376             not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())

KeyError: "None of [Index(['1'], dtype='object')] are in the [columns]"

 

이렇게 길고긴 오류가 반환되게 됩니다.

 

열 인덱스도 정수인 경우

 

그러면, 정수로만 이루어진 데이터프레임도 짜보겠습니다.

 

df2 = pd.DataFrame(np.arange(12).reshape(3, 4)) # 2차원 배열을 dataframe 으로 진행
df2

 

이러한 경우에는 정수로 인덱싱 하는 것도 가능합니다.

1열-2열 인덱싱

 

df2[[1,2]] # 정수 열 인덱스

 

데이터프레임의 행 인덱싱

 

행 단위로 인덱싱을 하려면, 항상 슬라이싱을 해야 합니다.

 

인덱스의 값이 문자 라벨이면 라벨 슬라이싱도 가능합니다.

 

df2[0:1]

 

자, 이경우 0번 행은 포함되나 1번행은 제외됩니다.

 

1~2번 행 인덱싱

df2[1:3]

 

* 문자열 인덱싱 ▶ 끝 행이 포함됩니다.

 

df['서울':'부산']

 

개별 데이터 인덱싱

 

개별적인 데이터도 인덱싱할 수 있습니다.

열 인덱싱을 한 상태, 즉 시리즈에서 이 시리즈를 다시 행 라벨로 인덱싱하면

각 개별 데이터가 나오게 됩니다.

 

▼열 인덱싱

 

df['2015']
서울    9904312
부산    3448737
인천    2890451
대구    2466052
Name: 2015, dtype: int64

 

▼붙여서 바로 행 인덱싱

 

df['2015']['서울']
9904312

 

인덱싱 부분은 직접 손으로 한번 해보면서 감을 잡는다면

금방 이해될 수 있을것이라 자명합니다.

 

데이터프레임의 갱신, 추가, 삭제

 

열 데이터

 

데이터프레임은 열 시리즈의 딕셔너리로 볼 수 있으므로

value의 추가도 아래와 같이 가능합니다.

 

- 추가 : 2005-2010 증가율 열 추가

# (2010 - 2005/2005) 100% 단위로 환산 --> 소수점 2번째 자리까지 반올림
df["2005-2010 증가율"] = ((df["2010"]-df["2005"])/df["2005"]*100).round(2)
df

 

 

- 갱신 : 2010-2015 증가율에 *100하기

df['2010-2015 증가율'] = df['2010-2015 증가율'] * 100
df

 

- 삭제 : 삭제는 del 메서드가 따로 존재합니다.

 

원래 데이터에는 2005-2010 증가율은 존재하지 않았죠?

다시 돌려놓아 볼까요?

 

2005-2010 증가율 삭제하기

 

del df["2005-2010 증가율"]
df

 

 

짜잔! 사라졌습니다.

 

인덱싱 loc 소개

 

여러분에게 loc 인덱서도 소개합니다!🎈

이러한 종류에는 loc 인덱서와 iloc 인덱서, 이렇게 2가지가 있는데

loc가 가지는 특징은 행인덱스 데이터로 인덱싱을 한다는 점입니다.

 

 

먼저 데이터프레임을 다시 한번 불러오겠습니다.

 

df = pd.DataFrame({
    "A": np.random.randint(5, size=5),
    "B": np.random.randint(5, size=5),
    "C": np.random.randint(5, size=5),
    "D": np.random.randint(5, size=5),
    "E": np.random.randint(5, size=5)
}, index=['a', 'b', 'c', 'd', 'e'])
df #1

 

일단 데이터는 randint로 뽑아놓았기 때문에

보시는 분들이 다시 실행하면 바뀔 수 있습니다!

 

 

행 인덱싱으로 시작합니다.

 

df.loc['a'] #행 열
A    0
B    0
C    2
D    4
E    4
Name: a, dtype: int64

 

'a' 행이 뽑히는데요.

열은 위에서 아래로, 데이터도 위에서 아래로 뽑히게 됩니다.

 

다양한 곳에 활용할 수 있습니다.

 

df.loc['b':'c'] # 행의 범위 >> 라벨 인덱스 > 끝0

 

행의 범위도 인덱싱 합니다.

 

df.loc[['d','e']] # 행의 라벨 인덱스 리스트

 

인덱스 리스트를 만들었습니다. 물론 가능합니다.

 

df.loc[df.A <=2] # 불리언 배열 인덱싱

 

2보다 작은 데이터들을 가져오는 것이죠.

조건 연산자를 사용합니다.

 

 

특히, 함수를 함께 사용할 수도 있습니다.

▼E 열 인덱스가 3보다 큰 값만 가져와 보겠습니다.

fun = lambda x: x.E >= 3 
df.loc[fun(df)] # 특정한 배열을 결과적으로 가져오는 함수

 

물론 3보다 작은 데이터가 대부분 이었습니다.

c 행 인덱스는 0 이었기 때문에 나오지 않았습니다.

 

 

단일 데이터도 가능합니다.

 

df.loc["a", "A"] # a행, A열
0

 

a행 A열의 데이터입니다.

 

df.loc["b":,"A"] # b행, A열
b    4
c    3
d    3
e    2
Name: A, dtype: int64

 

A 열에서 a 행을 제외하고 b행부터 뽑은 데이터입니다.

 

리스트 처럼 구성하여, 행 , 열의 방식으로 뽑을 수도 있습니다.

 

df.loc[["a", "b"], ["B", "D"]] # 리스트, 리스트 >> 행과 열만 선택

 

a~b행, B~D열 확인했습니다.

 

df.loc[df.A > 2, ["C", "D"]] # 조건 넣어서 처리

 

위처럼 조건을 넣어서 처리할 수도 있습니다.

 

df.loc["a",:] # a행의 모든 열을 의미함
A    0
B    0
C    2
D    4
E    4
Name: a, dtype: int64

 

a행'만' 뽑아냈습니다.

 

자 인덱서의 종류를 모두 알아봤을까요?

여기가 끝일까요?

 

 

 

하지만 잔짜잔!

또 있습니다✨✨

 

iloc 인덱서 소개

 

iloc 인덱서는 loc 인덱서와 달리 라벨이 아니라 순서를 나타내는

정수(integer) 인덱스만 받습니다 (다른 사항은 loc와 동일해요)

 

데이터프레임 다시 하나 만들겠습니다.

 

 

아래처럼 뽑아보겠습니다.

 

df.iloc[0, 1]
11

 

[행, 열]에 있는 값이 나타납니다.

 

df.iloc[:2, 2] # 정수 인덱싱 -> 라벨 인덱싱(끝값 제외)
a    12
b    16
Name: C, dtype: int64

 

정수 인덱스가 곧 라벨 인덱싱이 됩니다.

끝에 있는 값은 제외되죠.

 

df.iloc[-1]
A    2
B    2
C    2
D    1
E    3
Name: e, dtype: int64

 

인덱스상에서 -1일 경우, 뒤바꿔서 시작되는 것을 확인할 수 있습니다.

 

df.iloc[0, -2:]
C    12
D    13
Name: a, dtype: int64

 

위와 원리는 같습니다.

마찬가지로 역순입니다.

 

df.iloc[2:3, 1:3]

이렇게 데이터프레임으로 인덱싱도 가능하죠.

 

 


이상으로, pandas의 두번째 단계는 마치겠습니다.

 

*손으로 하는 실습은 항상 도움이 됩니다🏆🏆

728x90