Numpy로 수치계산하기 (2)
기본 배열 조작
먼저 1부터 10까지의 정수 배열을 만든다.
1 2 3 4 5 6 7 | >>> import numpy as np >>> >>> x = np.arange(1, 11) >>> >>> x array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) | cs |
조작 테이블을 만들기 위해 먼저 x 를 행과 열로 변환하자. x 는 1D 배열이지만 행과 열 벡터는 2D 배열(매트릭스)이다.
1) reshape( ) 를 이용한 방법
1 2 3 4 5 | >>> x_row = x.reshape((1, -1)) >>> >>> x_row >>> array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]) | cs |
reshape( ) 메소드는 파라메터로 새 크기를 받는다. 원소의 총 개수는 그대로 유지해야 한다. 예를 들어, (2, 3) 배열을 (5, 0) 배열로 변환하면 오류가 발생한다. -1 은 해당 축의 크기를 NumPy가 자동으로 인식하라는 것이다.
2개의 대괄호는 x_row 는 하나의 행으로 된 2D 배열을 나타내는 반면 x 는 1D 배열이다.
NumPy 에서 첫 번째 축은 수직행이고, 두 번째 축은 수평행이다.
2) 특수 인덱싱 문법을 사용하는 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> x_col = x[:, np.newaxis] >>> >>> x_col array([[ 1], [ 2], [ 3], [ 4], [ 5], [ 6], [ 7], [ 8], [ 9], [10]]) | cs |
여기서 콜론( : )은 첫 번째 축 전체를 선택하고자한다는 의미이고, 새로운 두 번째 축을 만들기 위해 np.newaxis 를 사용했다.
이제 매트릭스를 만들어보자. 두 벡터 간에 매트릭스 곱을 하기 위해 np.dot( )을 사용한다. x_col (10, 1) 배열과 x_row (1, 10) 배열이기 때문에 매트릭스 곱은 (10, 10) 배열이다.
1 2 3 4 5 6 7 8 9 10 11 12 | >>> np.dot(x_col, x_row) >>> array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20], [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30], [ 4, 8, 12, 16, 20, 24, 28, 32, 36, 40], [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50], [ 6, 12, 18, 24, 30, 36, 42, 48, 54, 60], [ 7, 14, 21, 28, 35, 42, 49, 56, 63, 70], [ 8, 16, 24, 32, 40, 48, 56, 64, 72, 80], [ 9, 18, 27, 36, 45, 54, 63, 72, 81, 90], [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]) | cs |
다른 방법으로 * 기호로 NumPy 곱셈을 하는 방법이 있다. 배열에서 이 연산은 매트릭스 곱셈이 아닌 원소 단위 곱셈이다.
1 2 3 4 5 6 7 8 9 10 11 12 | >>> x_row * x_col >>> array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20], [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30], [ 4, 8, 12, 16, 20, 24, 28, 32, 36, 40], [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50], [ 6, 12, 18, 24, 30, 36, 42, 48, 54, 60], [ 7, 14, 21, 28, 35, 42, 49, 56, 63, 70], [ 8, 16, 24, 32, 40, 48, 56, 64, 72, 80], [ 9, 18, 27, 36, 45, 54, 63, 72, 81, 90], [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]) | cs |
NumPy 로 배열계산
NumPy 로 배열을 다뤄보자.NYC 택시 데이터를 로드하여 판다 DataFrame 의 .values 로 ndarray 로 택시 승하차 위치를 구한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | >>> import numpy as np >>> import pandas as pd >>> import matplotlib.pyplot as plt >>> import seaborn as sns >>> %matplotlib inline >>> >>> data = pd.read_csv('data/nyc_data.csv', parse_dates = ['pickup_datetime', 'dropoff_datetime']) >>> >>> pickup = data[['pickup_longitude', 'pickup_latitude']].values >>> dropoff = data[['dropoff_longitude', 'dropoff_latitude']].values >>> pickup array([[-73.955925, 40.781887], [-74.005501, 40.745735], [-73.969955, 40.79977 ], ..., [-73.993492, 40.729347], [-73.978477, 40.772945], [-73.987206, 40.750568]]) | cs |
NumPy 에서는 pickup[ i, j ] 와 같은 형태로 주어진 원소를 검색할 수 있다. pickup[ i, j ] 는 0 부터 시작하는 i 번째 행이며, 0 부터 시작하는 j 번째 열이다.
그리고 라인 5에서와 같이 시작 위치, 긑 위치, 간격을 선택하여 슬라이싱도 가능하다. 여기서는 [1, 1], [3, 1], [5, 1]에 있는 원소를 선택했다. 파이썬 슬라이싱 문법에서는 end 에 해당하는 값은 포함하지 않는다. start 나 end 가 생략되면 start 는 시작과 end 는 끝으로 설정된다. step 은 기본 1이다. 예를 들어, 1: 은 1:n:1 과 같고 n 은 축의 길이이다.
1 2 3 4 5 6 7 8 9 | >>> print(pickup[3, 1]) 40.755081 >>> pickup[1:7:2,1:] array([[ 40.745735], [ 40.755081], [ 40.768978]]) | cs |
실제 CSV 데이터에서 보면 다음과 같다.
모든 승차 위치의 경도와 위도를 다음과 같이 구할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 | >>> lon = pickup[:, 0] >>> lon array([-73.955925, -74.005501, -73.969955, ..., -73.993492, -73.978477, -73.987206]) >>> lat = pickup[:, 1] >>> lat array([ 40.781887, 40.745735, 40.79977 , ..., 40.729347, 40.772945, 40.750568]) | cs |
NumPy 필터링 연산
주어진 위치에서 출발한 모든 운행을 선택해보자. lon_min 과 lon_max 사이에 있는 경도로, 모든 운행에서 선택해보자. 결과는 lon 벡터에 있는 원소에 대한 Boolean 벡터다.
1 2 3 4 5 6 7 | >>> lon_min, lon_max = (-73.98330, -73.98025) >>> lat_min, lat_max = (40.76724, 40.76871) >>> >>> in_lon = (lon_min <= lon) & (lon <= lon_max) >>> in_lon array([False, False, False, ..., False, False, False], dtype=bool) | cs |
sum( ) 메소드를 이용하여 모든 원소의 합을 반환할 수 있다. False 원소는 0 으로, 그리고 True 원소는 1 로 변환한다. 그러므로, 합은 True 인 원소의 개수가 된다.
1 2 3 | >>> in_lon.sum() 69163 | cs |
마찬가지로 위도도 처리해보자.
1 2 3 4 | >>> in_lat = (lat_min <= lat) & (lat <= lat_max) >>> in_lat.sum() 16110 | cs |
위도와 경도에 해당하는 사각에 속한 모든 운행을 구해보자.
1 2 3 4 | >>> in_lonlat = in_lon & in_lat >>> in_lonlat.sum() 3998 | cs |
np.nonzero( ) 함수는 다음과 같이 불린 배열에서 True에 해당하는 인덱스를 반환한다.
1 2 3 | >>> np.nonzero(in_lonlat)[0] array([ 901, 1011, 1066, ..., 845749, 845903, 846080]) | cs |
마지막으로 하차 좌표가 필요하다. T 속성은 매트릭스의 전치이다. 여기서 dropoff.T 는 (2, N)의 배열로, 첫 행은 경도이며, 두 번째 행은 위도이다.
1 2 3 4 5 6 7 | >>> lon1, lat1 = dropoff.T >>> lon1, lat1 (array([-73.963181, -73.964943, -73.954567, ..., -74.013725, -73.963814, -73.970909]), array([ 40.777832, 40.755722, 40.787392, ..., 40.702332, 40.773922, 40.795815])) | cs |
배열에서의 수학연산
모든 승하차 위치를 NumPy 배열로 만들었다. 모든 운행에서 두 위치간의 거리를 구해보자. 두 위치간 거리를 구하는 공식은 아래 링크를 참고한다.
※ Formula and code for calculating distance based on two lat/lon locations
http://jan.ucc.nau.edu/~cvm/latlon_formula.html
모든 택시 운행의 직선거리를 계산하여 히스토그램으로 나타내보면 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | >>> EARTH_R = 6372.8 >>> >>> def geo_distance(lon0, lat0, lon1, lat1): >>> lat0 = np.radians(lat0) >>> lon0 = np.radians(lon0) >>> lat1 = np.radians(lat1) >>> lon1 = np.radians(lon1) >>> dlon = lon0 - lon1 >>> y = np.sqrt( >>> (np.cos(lat1) * np.sin(dlon)) ** 2 >>> + (np.cos(lat0) * np.sin(lat1) >>> - np.sin(lat0) * np.cos(lat1) * np.cos(dlon)) ** 2) >>> x = np.sin(lat0) * np.sin(lat1) + np.cos(lat0) * np.cos(lat1) * np.cos(dlon) >>> c = np.arctan2(y, x) >>> return EARTH_R * c >>> >>> distances = geo_distance(lon, lat, lon1, lat1) >>> >>> lon[:10], lat[:10], lon1[:10], lat1[:10], distances[:10] (array([-73.955925, -74.005501, -73.969955, -73.991432, -73.966225, -73.955238, -73.98558 , -73.999413, -73.99218 , -74.006554]), array([ 40.781887, 40.745735, 40.79977 , 40.755081, 40.773716, 40.768978, 40.752197, 40.730137, 40.738644, 40.74054 ]), array([-73.963181, -73.964943, -73.954567, -73.991417, -73.955399, -73.994064, -73.988777, -73.983047, -73.973099, -73.980469]), array([ 40.777832, 40.755722, 40.787392, 40.755085, 40.782597, 40.720299, 40.737244, 40.741844, 40.749355, 40.730408]), array([ 7.59535877e-01, 3.59342825e+00, 1.89062515e+00, 1.33984499e-03, 1.34431257e+00, 6.32615091e+00, 1.68484565e+00, 1.89684673e+00, 2.00118747e+00, 2.47044801e+00])) >>> plt.hist(distances[in_lonlat], np.linspace(0., 10., 50)) >>> plt.xlabel('Trip distance (km)') >>> plt.ylabel('Number of trips') >>> <matplotlib.text.Text at 0x7f7c6ff29c10> | cs |
'프로그래밍 Programming' 카테고리의 다른 글
결정트리와 타이타닉 가설 설명 (1) - 데이터 전처리 (0) | 2016.11.22 |
---|---|
Numpy로 수치계산하기 (3) (0) | 2016.11.19 |
Numpy로 수치계산하기 (1) (0) | 2016.11.18 |
텍스트 분류를 위한 나이브 베이즈 (2) - 분류기 훈련 및 성능평가 (0) | 2016.11.15 |
우분투에 스칼라 설치하기 Install Scala on Ubuntu 14.04 (0) | 2016.11.14 |