2017년 2학기 공업수학 기말고사 시험지

이름:

학번:

모듈 임포트

코드를 실행하기 위해 필요한 모듈들이다.


In [1]:
from __future__ import division, print_function
import numpy as np
import pandas as pd
from datetime import datetime as dt

넘파이 어레이

아래 모양의 어레이를 생성하기 위해 reshape 함수를 이용한다.

$$\left [ \begin{matrix} 1 & 3 \\ 5 & 7 \\ 9 & 11 \end{matrix} \right ]$$

In [2]:
a = np.arange(1, 12, 2)
b = a.reshape(3,2)
b


Out[2]:
array([[ 1,  3],
       [ 5,  7],
       [ 9, 11]])

추가로 아래 코드를 실행하자.


In [3]:
b[2,1] = 3

문제 1

(1) a의 값은 어떻게 변경되었는지 설명하라. (5점)


In [4]:
a


Out[4]:
array([1, 3, 5, 7, 9, 3])

(2) 위와 같은 현상이 발생하는 이유를 설명하라. (5점)

reshape 함수가 뷰 방식을 따르기 때문이다. 즉, 변수 b에 할당하는 어레이를 메모리를 실제로 조작하여 생성하지 않으면서 기존에 생성된 a에 할당된 어레이를 지켜보면서 필요한 정보만 얻어온다.

(3) 위와 같은 현상을 피하기 위해서는 어떻게 해야 하는지 설명하라. (5점)

아래와 같이 copy 함수를 이용해야 한다.


In [5]:
a = np.arange(1, 12, 2)
b = a.reshape(3,2).copy()
b[2,1] = 3
a


Out[5]:
array([ 1,  3,  5,  7,  9, 11])

넘파이 어레이 인덱싱/슬라이싱

아래 코드로 생성된 어레이를 이용하는 문제이다.


In [6]:
a = np.arange(6) + np.arange(0, 51, 10)[:, np.newaxis]
a


Out[6]:
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])

a 어레이를 이용하여 예를 들어 아래 모양의 어레이를 생성할 수 있다.

$$\left [ \begin{matrix} 20 & 22 \\ 40 & 42 \end{matrix} \right ]$$

In [7]:
a[2::2, :4:2]


Out[7]:
array([[20, 22],
       [40, 42]])

문제 2

(1) a 어레이에 인덱싱과 슬라이싱을 이용하여 아래 모양의 어레이를 생성하라. (5점)

$$\left [ \begin{matrix} 20 & 21 & 22 \\ 40 & 41 & 42 \end{matrix} \right ]$$

In [8]:
a[2::2, :3]


Out[8]:
array([[20, 21, 22],
       [40, 41, 42]])

(2) a 어레이에 인덱싱과 슬라이싱을 이용하여 아래 모양의 어레이를 생성하라. (5점)

$$\left [ \begin{matrix} 5 & 15 & 25 & 35 & 45 & 55 \end{matrix} \right ]$$

In [9]:
a[:, 5]


Out[9]:
array([ 5, 15, 25, 35, 45, 55])

또는


In [10]:
a[:, 5:].flatten()


Out[10]:
array([ 5, 15, 25, 35, 45, 55])

주의: 아래는 다른 값이 나옴


In [11]:
a[5, :]


Out[11]:
array([50, 51, 52, 53, 54, 55])

(3) 마스크 인덱싱을 사용하여 아래 결과가 나오도록 하라. (10점)

array([ 0,  3, 12, 15, 21, 24, 30, 33, 42, 45, 51, 54])

In [12]:
mask = a % 3 == 0
a[mask]


Out[12]:
array([ 0,  3, 12, 15, 21, 24, 30, 33, 42, 45, 51, 54])

또는


In [13]:
a[a % 3 == 0]


Out[13]:
array([ 0,  3, 12, 15, 21, 24, 30, 33, 42, 45, 51, 54])

정수 인덱싱

정수 인덱싱을 사용하여 아래 결과가 나오도록 할 수 있다.

array([ 12, 23, 34])

In [14]:
a[(1, 2, 3), (2, 3, 4)]


Out[14]:
array([12, 23, 34])

(4) 정수 인덱싱을 사용하여 아래 모양의 어레이가 나오도록 하라. (10점)

$$\left [ \begin{matrix} 30 & 32 & 35 \\ 50 & 52 & 55 \end{matrix} \right ]$$

In [15]:
a[3::2, (0, 2, 5)]


Out[15]:
array([[30, 32, 35],
       [50, 52, 55]])

아래와 같이 할 수도 있다.


In [16]:
a[(3, 3, 3, 5, 5, 5), (0, 2, 5, 0, 2, 5)].reshape(2,3)


Out[16]:
array([[30, 32, 35],
       [50, 52, 55]])

또는


In [17]:
b = a[(3, 3, 3, 5, 5, 5), (0, 2, 5, 0, 2, 5)]
b.shape = (2, 3)
b


Out[17]:
array([[30, 32, 35],
       [50, 52, 55]])

아래는 다른 값을 나타냄.


In [18]:
a[[(3, 3, 3), (0, 2, 5)], 
  [(5, 5, 5), (0, 2, 5)]]


Out[18]:
array([[35, 35, 35],
       [ 0, 22, 55]])

데이터 분석

오늘 사용할 데이터는 다음과 같다.

  • 미국 51개 주(State)별 담배(식물) 도매가격 및 판매일자: Weed_price.csv

아래 그림은 미국의 주별 담배(식물) 판매 데이터를 담은 Weed_Price.csv 파일를 엑셀로 읽었을 때의 일부를 보여준다. 실제 데이터량은 22899개이며, 아래 그림에는 5개의 데이터만을 보여주고 있다.

  • 주의: 1번줄은 테이블의 열별 목록(column names)을 담고 있다.
  • 열별 목록: State, HighQ, HighQN, MedQ, MedQN, LowQ, LowQN, date

문제 3

(1) 아래 코드를 설명하라. (5점)


In [19]:
prices_pd = pd.read_csv("data/Weed_Price.csv", parse_dates=[-1])

datal 디렉토리에 저장되어 있는 Weed_Price.csv 파일을 불러온다. 단, par_dates=[-1]에 의해 날짜정보는 변형시키지 않은채 그대로 불러온다.

날짜 및 시간에 대한 정보를 일반적으로 시계열 자료형이라 하며 중요한 역할을 수행한다. 따라서 특별한 형식을 갖추도록 하는 게 중요한데 위 예제의 경우는 이미 표준형식으로 지정되어 있기에, 따로 변형을 가하지 않아도 된다.


In [20]:
prices_pd.head()


Out[20]:
State HighQ HighQN MedQ MedQN LowQ LowQN date
0 Alabama 339.06 1042 198.64 933 149.49 123 2014-01-01
1 Alaska 288.75 252 260.60 297 388.58 26 2014-01-01
2 Arizona 303.31 1941 209.35 1625 189.45 222 2014-01-01
3 Arkansas 361.85 576 185.62 544 125.87 112 2014-01-01
4 California 248.78 12096 193.56 12812 192.92 778 2014-01-01

(2) 아래 코드를 설명하라. (10점)


In [21]:
prices_pd.sort_values(['State', 'date'], inplace=True)

prices_pd 에 저장된 테이블을 State 이름과, date 날짜 순으로 정렬하라는 명령어이며, 정렬한 결과가 다시 prices_pd 변수에 할당된다.

주의: 먼저 State 기준으로 정렬한 후에, 각 주 별로 date 기준으로 정렬한다.

주의: pandas의 DataFrame 자료형은 가변(mutable)이며, inplace 키워드 인자값이 True 설정되었기에 기존의 테이블에 직접 수정을 가한다.


In [22]:
prices_pd.head()


Out[22]:
State HighQ HighQN MedQ MedQN LowQ LowQN date
20094 Alabama 339.65 1033 198.04 926 147.15 122 2013-12-27
20859 Alabama 339.65 1033 198.04 926 147.15 122 2013-12-28
21573 Alabama 339.75 1036 198.26 929 149.49 123 2013-12-29
22287 Alabama 339.75 1036 198.81 930 149.49 123 2013-12-30
22797 Alabama 339.42 1040 198.68 932 149.49 123 2013-12-31

기존의 테이블을 수정하지 않은채로 다른 변수에 저장하려면 아래와 같이 실행한다.

prices_pd = pd.read_csv("data/Weed_Price.csv", parse_dates=[-1])
prices_pd_sorted = prices_pd.sort_values(['State', 'date'])

아래 문제의 답을 확인하기 전에 아래 결과를 기억해 두어야 한다.


In [23]:
prices_pd.tail()


Out[23]:
State HighQ HighQN MedQ MedQN LowQ LowQN date
4997 Wyoming 313.72 148 317.38 226 NaN 13 2015-06-07
5762 Wyoming 313.72 148 317.38 226 NaN 13 2015-06-08
6527 Wyoming 313.72 148 317.38 226 NaN 13 2015-06-09
7343 Wyoming 313.72 148 317.38 226 NaN 13 2015-06-10
8159 Wyoming 313.72 148 317.38 226 NaN 13 2015-06-11

위 테이블은 정렬된 주별, 날짜별로 정리된 테이블의 마지막 5줄을 보여주고 있으며, LowQ 컬럼의 일부 값이 NaN, 즉 결측치로 처리되어 있음에 주의하라.

아래 문제는 그런 결측치를 다른 값으로 채우는 방식에 대해 다루고 있다.

(3) 아래 코드를 설명하라. (5점)


In [24]:
prices_pd.fillna(method='ffill', inplace=True)

테이블에 포함된 결측치(NaN 값)들을 ffill 방식으로 채운다.

  • ffill = forward fill 방식의 줄임말이며, 결측치의 위치 위쪽으로부터 가장 가까운 값을 이용하여 결측치가 채워진다.
  • inplace=True: 앞서 설명한 대로 기존의 테이블에 직접 수정을 가한다.

아래 실행결과는 테이블의 마지작 5줄의 LowQ 컬럼의 값들이 161.3으로 채워졌는데 그 값이 위쪽 방향으로 가장 가까운 위치에 사용된 값이기 때문이다.


In [25]:
prices_pd.tail()


Out[25]:
State HighQ HighQN MedQ MedQN LowQ LowQN date
4997 Wyoming 313.72 148 317.38 226 161.3 13 2015-06-07
5762 Wyoming 313.72 148 317.38 226 161.3 13 2015-06-08
6527 Wyoming 313.72 148 317.38 226 161.3 13 2015-06-09
7343 Wyoming 313.72 148 317.38 226 161.3 13 2015-06-10
8159 Wyoming 313.72 148 317.38 226 161.3 13 2015-06-11

(4) 아래 코드를 설명하라. (5점)


In [26]:
california_pd = prices_pd[prices_pd.State == "California"].copy(True)

마스트 인덱싱을 사용하여 주 이름이 California 인 행만 포함된 테이블을 california_pd 변수에 저장한다. 사용된 마스크는 다음과 같다.

prices_pd.State == "California"

주의: copy(True)를 사용하였기에 뷰 방식을 사용하지 않도록 하였다.


In [27]:
california_pd.head()


Out[27]:
State HighQ HighQN MedQ MedQN LowQ LowQN date
20098 California 248.77 12021 193.44 12724 193.88 770 2013-12-27
20863 California 248.74 12025 193.44 12728 193.88 770 2013-12-28
21577 California 248.76 12047 193.55 12760 193.60 772 2013-12-29
22291 California 248.82 12065 193.54 12779 193.80 773 2013-12-30
22801 California 248.76 12082 193.54 12792 193.80 773 2013-12-31

(5) 아래 코드를 설명하라. (10점)


In [28]:
ca_sum = california_pd['HighQ'].sum()
ca_count = california_pd['HighQ'].count()
ca_sum / ca_count


Out[28]:
245.3761247216035

HighQ 컬럼에 포함된 값들의 평균값(mean)을 계산한 결과이다.

  • ca_sum: HighQ 컬럼의 값들을 모두 더한 결과가 저장된다.
  • ca_count: HighQ 컬럼에 포함된 값들의 개수가 저장된다.
  • 평균값 = (값들의 함) / (값들의 개수)

(6) 아래 코드를 설명하라. (10점)


In [29]:
def getYear(x):
    return x.year

year_col = prices_pd.date.apply(getYear)
prices_pd["year"] = year_col

year_col은 prices_pd에 저장된 테이블의 date 컬럼에서 연도만을 추출한 결과를 Series 자료형으로 갖고 있다.


In [30]:
year_col.head()


Out[30]:
20094    2013
20859    2013
21573    2013
22287    2013
22797    2013
Name: date, dtype: int64

이제 year_col에 저장된 시리즈를 prices_pd 테이블에 year라는 컬럼으로 추가한다.


In [31]:
prices_pd.head()


Out[31]:
State HighQ HighQN MedQ MedQN LowQ LowQN date year
20094 Alabama 339.65 1033 198.04 926 147.15 122 2013-12-27 2013
20859 Alabama 339.65 1033 198.04 926 147.15 122 2013-12-28 2013
21573 Alabama 339.75 1036 198.26 929 149.49 123 2013-12-29 2013
22287 Alabama 339.75 1036 198.81 930 149.49 123 2013-12-30 2013
22797 Alabama 339.42 1040 198.68 932 149.49 123 2013-12-31 2013

(7) 아래 코드를 설명하라. (10점)


In [32]:
price_ca14 = prices_pd[(prices_pd.State=="California") & \
                       (prices_pd.year==2014)].head()

마스크 인덱싱을 사용하여 California 주에서 2014년도에 거래된 정보들만 추출하여 price_ca14에 저장한다. 사용한 마스크는 다음과 같다.

(prices_pd.State=="California") & (prices_pd.year==2014)

주의: 처음 5줄만 저장된다. 또한 prices_pd에 저장된 테이블이 이전에 State 와 date 기준으로 정렬되어 있다. 따라서 포함된 5줄 모두 Alabama 주에서 2013년에 거래된 데이터이다.


In [33]:
price_ca14


Out[33]:
State HighQ HighQN MedQ MedQN LowQ LowQN date year
4 California 248.78 12096 193.56 12812 192.92 778 2014-01-01 2014
769 California 248.67 12125 193.56 12836 192.80 779 2014-01-02 2014
1483 California 248.67 12141 193.57 12853 192.67 782 2014-01-03 2014
2248 California 248.65 12155 193.59 12884 192.67 782 2014-01-04 2014
3013 California 248.68 12176 193.63 12902 192.67 782 2014-01-05 2014