본문 바로가기
엑셈 경쟁력/시계열 데이터처리 AI 알고리즘

Chapter 2. Pandas 2편 : Time Series 머신러닝을 위한 Python 필수 라이브러리

by EXEM 2022. 8. 25.

2.2 Time Series 머신러닝을 위한 Python 필수 라이브러리, Pandas 2편

 

2.2.3 원소선택, 인덱싱

 

2.2.3.1 series 인덱싱
인덱싱은 [위치] 또는 [‘인덱스명’]으로 인덱싱이 가능하다.

 

In [7]:

 

 

 

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)

 

처리 속도는 atiat의 경우가 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의 경우도 indexcolumns를 선택할 때 마찬가지다.

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팀 김기중

 

 

 

 

댓글