인덱싱과 슬라이싱은 원하는 것만 골라 뽑는 인형뽑기 게임이라고 생각하는 건 어떨까요?
불필요한 것은 버리고 필요한 것만 싹 골라가는 능력은 중요합니다.
서론
※ 주의
다소 반복적인 내용이 소개될 수 있습니다😂
다만 추후에 데이터 전처리나 다듬는 단계에서 기본기처럼 사용될 수 있으니
확실하게 알고 넘어가는 것이 중요할 것입니다!
🤷♀️
다시 시리즈부터 확인해보겠습니다.
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의 두번째 단계는 마치겠습니다.
*손으로 하는 실습은 항상 도움이 됩니다🏆🏆
'Programming Language > Python_library' 카테고리의 다른 글
2KHz의 sin파 PyQt5로 구현 (0) | 2023.09.17 |
---|---|
파이썬_활용단계 ep.1 Let's go pandas 월드 (2) | 2022.12.14 |
파이썬_응용단계 ep.8 난수와 샘플링, 데이터 카운팅! (2) | 2022.12.13 |
파이썬_응용단계 ep.7 정렬과 통계 (0) | 2022.12.11 |
파이썬_응용단계 ep.6 배열의 연산 (0) | 2022.12.11 |