2.2 Time Series 머신러닝을 위한 Python 필수 라이브러리, Pandas 2편
2.2.3 원소선택, 인덱싱
2.2.3.1 series 인덱싱
인덱싱은 [위치] 또는 [‘인덱스명’]으로 인덱싱이 가능하다.
import pandas as pd
import numpy as np
series_data = [2,4,6,8]
series_data = pd.Series(series_data)
series_data
0 2
1 4
2 6
3 8
dtype: int64
In [7]:
series_data[1]
4
* 여러 값 인덱싱 및 슬라이싱
한 번에 여러 값을 인덱싱 하게 될 때는 위치나 인덱스명 둘 다 짝을 이루는 값을 모두 반환한다.
이때 각각의 인덱스 위치를 알고 싶거나, 여러 값을 인덱싱할 때는 괄호를 하나 더 씌워야 된다.
series_data[[0,2]]
0 2
2 6
dtype: int64
콜론(':') 으로 할 경우엔 마찬가지로 슬라이싱이 가능하다.
series_data[:3]
Out [10]:
0 2
1 4
2 6
dtype: int64
2.2.3.2 Dataframe 인덱싱
하나의 열을 가져오는 방법은 dataframe에서는 두 가지이다. 대표적으로 dataframe변수명[‘컬럼명’] (이때 하나의 열을 가져온 결과는 series 모양), 또는, dataframe변수명.컬럼명 이다.
Dataframe의 경우 슬라이싱 할 때 현재 방법으로는 가장 기본적인 인덱스에 관한 슬라이싱만 가능하다. 행렬에서 열에 대한 정보를 콜론을 통한 슬라이싱으로는 가져올 수 없다.
In [11]:
df = pd.DataFrame([[14,'남'],[17,'여'],[24,'남'],[20,'여'],[15,'남'],[21,'여']],
index = ['a','b','c','d','e','f'],
columns = ['나이','성별'])
In [12]:
df
Out [13]:
나이 성별
a 14 남
b 17 여
c 24 남
d 20 여
e 15 남
f 21 여
In [14]:
df[1:]
Out [15]:
나이 성별 성인
b 17 여 False
c 24 남 True
d 20 여 False
e 15 남 False
f 21 여 True
2.2.4 데이터 인덱싱, 슬라이싱 loc, iloc, at, iat
Dataframe을 사용하게 되었을 때 가장 많이 사용되는 함수이다. 데이터 전처리를 하거나 인덱싱과 슬라이싱에 항상 사용되기 때문이다.
2.2.4.1 loc
Index 이름으로 row의 정보를 추출할 때 사용된다.
그렇기 때문에 df.loc[‘a’]이라고 했을 때 df의 index에서 ‘a’이라는 이름을 가진 데이터를 찾아서 정보를 추출한다. 추가적으로 Dataframe 형태로 추출하고 싶다면 df.loc[:, [‘col_name’]]으로 하면 된다.
2.2.4.2 iloc
Index 번호로 row의 정보를 추출할 때 사용된다.
loc, iloc 차이를 알아보도록 하자.
In [16]:
df
Out [17]:
나이 성별 성인
a 14 남 False
b 17 여 False
c 24 남 True
d 20 여 False
e 15 남 False
f 21 여 True
In [18]:
df['나이']
Out [19]:
a 14
b 17
c 24
d 20
e 15
f 21
Name: 나이, dtype: int64
In [20]:
df.loc['a']
Out [21]:
나이 14
성별 남
성인 False
Name: a, dtype: object
In [22]:
df.iloc[0]
Out [23]:
나이 14
성별 남
성인 False
Name: a, dtype: object
2.2.4.3 패스트 인덱싱(at, iat)
처리 속도는 at와 iat의 경우가 loc, iloc보다 훨씬 빠른데, 이유는 하나의 요소 값을 선택하도록 되어있기 때문이다.
대용량 데이터를 처리할 때는 패스트 인덱싱을 사용하는것이 좋다. at, iat의차이는 위와 같이 인덱스 명으로 하거나 인덱스를 직접 넣는 형태로 같다.
In [24]:
df.at['a','나이']
Out [25]:
14
In [26]:
df.iat[0,0]
Out [27]:
14
장단점이 있으니 상황에 맞게 사용해보는 것을 추천한다.
2.2.5 산술연산
Pandas의 경우 산술연산은 내부적으로 3단계 프로세스를 거치게 된다.
1. 행/열 인덱스를 기준으로 모든 원소를 정렬한다.
2. 동일한 위치에 있는 원소끼리 일대일로 대응시킨다.
3. 일대일 대응이 되는 원소끼리 연산을 처리한다. 이때 원소가 없으면 NaN으로 처리하게 된다.
dataframe에서 봤을 때는 columns간의 연산은 series 연산이다.
series간의 연산은 같은 인덱스를 가진 원소끼리 연산하여 새로운 series를 반환해준다. 그리고 이외에 사칙연산 연산자도 가능하다. (-, *, /, %)
In [20]:
df = pd.DataFrame(np.arange(12).reshape(3,4), columns = ['a','b','c', 'd'])
In [28]:
df
Out [29]:
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
In [30]:
df['b'] + df['c']
Out [31]:
0 3
1 11
2 19
dtype: int32
2.2.5.1 Series 숫자 연산
Series와 숫자 연산은 series의 개별 원소에 각각 연산하여 새로운 series를 반환한다.
In [32]:
df['d'] + 10
Out [33]:
0 13
1 17
2 21
Name: d, dtype: int32
2.2.5.2 결측치(NaN)
Series 간의 계산을 할 때 하나의 인덱스라도 없을 경우 NaN이 출력된다.
In [32]:
df_2 = (pd.DataFrame(np.arange(9).reshape(3,3), columns = ['a','b','c']))
In [32]:
df + df_2
Out [33]:
a b c d
0 0 2 4 NaN
1 7 9 11 NaN
2 14 16 18 NaN
2.5.5.3 연산메소드
사칙연산을 직접 해줄 수도 있고, 연한함수도 따로 제공해서 가능하다. 그리고 NaN이 되는 경우엔 fill_value 옵션으로 값을 대체할 수 있다.
In [34]:
df.add(df_2, fill_value =0)
Out [35]:
a b c d
0 0 2 4 3.0
1 7 9 11 7.0
2 14 16 18 11.0
In [36]:
df.sub(df_2['a'], axis='index')
Out [37]:
a b c d
0 0 1 2 3
1 1 2 3 4
2 2 3 4 5
그 외에 메소드 산술연산에 관련된 함수들
df.add(num), | Dataframe에 스칼라 값 더하기 |
df.sub(num) | Dataframe에 스칼라 값 빼기 |
df.mul(num), | Dataframe에 스칼라 값 곱하기 |
df.div(num) | Dataframe에 스칼라 값 나누기 |
df.pow(num) | Dataframe에 스칼라 값 n승 |
.
2.2.6 함수 매핑
Numpy와 같이 개별 원소를 특정 함수에 일대일 대응할 수 있다. (ufunc) 그렇기 때문에 직접 만든 함수나 lambda를 적용할 수 있기 때문에 for문이나 기본 함수로 처리하는 것보다 훨씬 효율적이다.
apply () -> series 개별원소에 함수를 적용할 때 사용되고 dataframe에서도 가능하다.
In [38]:
def add_10(n):
return n + 10
In [39]:
df
Out [40]:
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
In [41]:
df.apply(add_10)
Out [42]:
a b c d
0 10 11 12 13
1 14 15 16 17
2 18 19 20 21
매핑함수들 또한 series 인지 dataframe인지에 따라 가능여부가 다르다. 경우를 생각하지 않고 함수를 만들어서 사용한다고 하면 apply가 가장 무난하다.
2.2.7 데이터 정렬
정렬은 원하는 데이터 값을 얻고자 한다면 반드시 필요로 한다. 이때 정렬은 크게 column, row의 두 가지 형태를 인덱스를 바탕으로 정렬할 수 있다.
2.2.7.1 Sort_index()
가장 기본적인 Row의 인덱스를 바탕으로 정렬하는 방법이다.
In [43]:
df = pd.DataFrame([[11,21],[14,24],[12,22],[13,23],[10,20],[15,25]], index=[1,4,2,6,3,0], columns=['b','a'])
In [44]:
df
Out [45]:
b a
1 11 21
4 14 24
2 12 22
6 13 23
3 10 20
0 15 25
In [46]:
df.sort_index(ascending=False)
Out [47]:
b a
6 13 23
4 14 24
3 10 20
2 12 22
1 11 21
0 15 25
Column 기반으로 정렬하기
마찬가지로 axis로 축을 변경해줌으로써 columns 간에도 정렬이 가능하다.
In [48]:
df.sort_index(axis=1)
Out [49]:
a b
1 21 11
4 24 14
2 22 12
6 23 13
3 20 10
0 25 15
값 기반으로 정렬하기
By 옵션을 통해 정렬을 할 수 있다. 즉 기준이 되는 컬럼 인덱스를 입력해 줘야 되고, 2개를 입력하게 된다면, 앞에 column 기준으로 정렬을 하게 되고, 다음에 오는 column을 정렬하게 된다.
In [50]:
df.sort_values(by=['a','b'])
Out [51]:
b a
3 10 20
1 11 21
2 12 22
6 13 23
4 14 24
0 15 25
2.2.8 중복 인덱스 확인 및 처리
평소에 다루는 데이터의 경우 여러 파일을 한 번에 받아 합치게 되면, 인덱스가 겹치는 경우가 있다. 이러한 경우 인덱싱을 할 때 중복되는 인덱스가 있게 된다면 결과가 달라질 수 있기 때문에 중복 처리를 하는 것이 좋다고 생각된다. is_unique를 통해 간단하게 인덱스 중복 확인이 가능하다.
In [52]:
series = pd.Series(range(10), index=['a','b','c','c','d','e','e','f','g','i'])
In [53]:
series
Out [54]:
a 0
b 1
c 2
c 3
d 4
e 5
e 6
f 7
g 8
i 9
dtype: int64
In [55]:
series.index.is_unique
Out [56]:
False
유일한 값으로만 되어있는 경우
In [57]:
series_2 = pd.Series(range(3), index=['a','b','c'])
In [58]:
series_2.index.is_unique
Out [59]:
True
Dataframe의 경우도 index와 columns를 선택할 때 마찬가지다.
In [60]:
df = pd.DataFrame(np.arange(36).reshape(6,6), index=[1,2,2,3,3,4], columns=['a','a','b','b','c','c'])
In [61]:
df
Out [62]:
a a b b c c
1 0 1 2 3 4 5
2 6 7 8 9 10 11
2 12 13 14 15 16 17
3 18 19 20 21 22 23
3 24 25 26 27 28 29
4 30 31 32 33 34 35
In [63]:
df['b']
Out [64]:
b b
1 2 3
2 8 9
2 14 15
3 20 21
3 26 27
4 32 33
In [65]:
df.loc[3,'b']
Out [66]:
b b
3 20 21
3 26 27
1차원 series에 담긴 정보를 추출하는 unique()라는 함수도 존재한다. 그리고 만약 순서와 유일한 값이 필요없고 빈도수를 확인하고 싶으면 value_counts()를 사용해서 확인이 가능하다
In [67]:
series = pd.Series(['a','b','c','c','d','e','e','f','g','i'])
In [68]:
series.unique()
Out [69]:
array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'], dtype=object)
In [70]:
series.value_counts()
Out [71]:
c 2
e 2
b 1
i 1
g 1
d 1
f 1
a 1
dtype: int64
추가적인 메소드
df.isin([num..]) | Series의 각각의 요소가 존재하는지 boolean으로 반환 |
df[‘col_name’].Unique() | series에서 중복되는 값을 제거하고 유일값만 포함하는 배열 반환 |
df.[‘col_name’].Value_counts() | sereis에서 유일값에 대한 인덱싱과 개수를 세어준다. |
2.2.9 기술 통계 계산과 요약
각각의 결과를 보기 위한 함수가 여러 가지 있지만, 전체적으로 볼 수 있는 함수 df.describe()를 활용해보자.
In [72]:
df = pd.DataFrame(np.arange(36).reshape(6,6), index=[1,2,3,4,5,6], columns=['a','b','c','d','e','f'])
In [73]:
df.describe()
Out [74]:
a b c d e f
count 6.000000 6.000000 6.000000 6.000000 6.000000 6.000000
mean 15.000000 16.000000 17.000000 18.000000 19.000000 20.000000
std 11.224972 11.224972 11.224972 11.224972 11.224972 11.224972
min 0.000000 1.000000 2.000000 3.000000 4.000000 5.000000
25% 7.500000 8.500000 9.500000 10.500000 11.500000 12.500000
50% 15.000000 16.000000 17.000000 18.000000 19.000000 20.000000
75% 22.500000 23.500000 24.500000 25.500000 26.500000 27.500000
max 30.000000 31.000000 32.000000 33.000000 34.000000 35.000000
통계 관련 메소드
df.count() | 행/열에 대해 Nan을 제외한 값의 개수 반환 |
df.min(), df.max() | 행/열에 대해 최대 최소 값 반환 |
df.argmin(), df.argmax() | 행/열에 대해 최대 최소 값의 인덱스 반환 |
df.idxmin(), df.idxmax() | 행/열에 대해 최대 최소 값을 가진 인덱스의 값 반환 |
df.sum() | 합 리턴 |
df.mean() | 평균 리턴 |
df.median() | 중간값(50% 분위)을 반환 |
df.mad() | 평균값에서 평균절대 편차를 계산 |
df.prod() | 모든 값의 곱 |
df.std() | 표준편차의 값 계산 |
df.var() | 표본분산의 값 계산 |
df.cumsum() | 누적합을 계산 |
df.summin(), df.cummax() | 누적 최소, 최댓값을 계산 |
df.cumprod() | 누적곱 계산 |
이번 페이지에서는 dataframe을 조금 더 자세하게 다루는 방법을 알아보았다. 다음 페이지에서는 데이터 로드 및 저장, 결측치 처리, dataframe 처리팁 등을 알아보도록 하자.
기획 및 글 | AI 1팀 김기중
'엑셈 경쟁력 > 시계열 데이터처리 AI 알고리즘' 카테고리의 다른 글
Chapter 2-2. 시계열 데이터 전처리 (0) | 2022.09.28 |
---|---|
Chapter 2. Pandas 3편 : Time Series 머신러닝을 위한 Python 필수 라이브러리 (0) | 2022.08.25 |
Chapter 2. Pandas 1편 : Time Series 머신러닝을 위한 Python 필수 라이브러리 (0) | 2022.08.25 |
Chapter 2. Numpy 2편 : Time Series 머신러닝을 위한 Python 필수 라이브러리 (0) | 2022.07.27 |
Chapter 2. Numpy 1편 : Time Series 머신러닝을 위한 Python 필수 라이브러리 (0) | 2022.07.27 |
댓글