ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (DACON) 아파트 실거래가 예측 튜토리얼 대회
    IT 지식 창고 2019. 7. 7. 16:47

    데이콘에서 주최한 제 2회 튜토리얼 대회입니다.

     

    https://dacon.io/tutorial_comp/116748

     

    튜토리얼

     

    dacon.io

    1회대회에 아쉽게 실격 처리가 되어 2번째 대회에 다시 도전하여 총 14팀중 5등으로 수상하게 되었습니다. 

     

     

    약 150만개의 데이터를 처음 다뤄보면서 컴퓨터의 한계에 부딪히기도 하였고, colab을 이용하여 데이터를 학습하는 방법을 배웠습니다.

     

     

    아파트 실거래가 예측-최종정리
    In [1]:
    #주피터 노트북 블로그게시용 함수
    from IPython.core.display import display, HTML
    display(HTML("<style> .container{width:100% !important;}</style>"))
    
    In [1]:
    # For example, here's several helpful packages to load in 
    
    import numpy as np # linear algebra
    import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
    
    import matplotlib.pyplot as plt #data visualization
    import seaborn as sns
    
    import timeit # time measure
    
    import sklearn # modeling
    
    import warnings
    warnings.filterwarnings("ignore")
    
    import sys
    
    print ('Python version ->', sys.version)
    print ('Numpy version ->', np.__version__)
    print ('Pandas version ->', pd.__version__)
    print ('Sklearn version ->', sklearn.__version__)
    
    Python version -> 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)]
    Numpy version -> 1.16.0
    Pandas version -> 0.24.0
    Sklearn version -> 0.19.2
    

    1. Data set 불러오기

    In [2]:
    train_df = pd.read_csv('train.csv') # training dataframe
    test_df = pd.read_csv('test.csv') # testing dataframe
    
    In [3]:
    #원본데이터는 보존하기 위함
    train = train_df.copy()
    test = test_df.copy()
    
    In [4]:
    print("train.csv. Shape: ",train.shape)
    print("test.csv. Shape: ",test.shape)
    
    train.csv. Shape:  (1216553, 13)
    test.csv. Shape:  (5463, 12)
    
    In [5]:
    train.info()
    
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 1216553 entries, 0 to 1216552
    Data columns (total 13 columns):
    transaction_id            1216553 non-null int64
    apartment_id              1216553 non-null int64
    city                      1216553 non-null object
    dong                      1216553 non-null object
    jibun                     1216553 non-null object
    apt                       1216553 non-null object
    addr_kr                   1216553 non-null object
    exclusive_use_area        1216553 non-null float64
    year_of_completion        1216553 non-null int64
    transaction_year_month    1216553 non-null int64
    transaction_date          1216553 non-null object
    floor                     1216553 non-null int64
    transaction_real_price    1216553 non-null int64
    dtypes: float64(1), int64(6), object(6)
    memory usage: 120.7+ MB
    
    In [6]:
    test.info()
    
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 5463 entries, 0 to 5462
    Data columns (total 12 columns):
    transaction_id            5463 non-null int64
    apartment_id              5463 non-null int64
    city                      5463 non-null object
    dong                      5463 non-null object
    jibun                     5463 non-null object
    apt                       5463 non-null object
    addr_kr                   5463 non-null object
    exclusive_use_area        5463 non-null float64
    year_of_completion        5463 non-null int64
    transaction_year_month    5463 non-null int64
    transaction_date          5463 non-null object
    floor                     5463 non-null int64
    dtypes: float64(1), int64(5), object(6)
    memory usage: 512.2+ KB
    

    Train Column name Description

    • transaction_id : 아파트 거래에 대한 유니크한 아이디
    • apartment_id : 아파트 아이디
    • city : 도시
    • dong : 동
    • jibun : 지번
    • apt : 아파트단지 이름
    • addr_kr : 주소
    • exclusive_use_area : 전용면적
    • year_of_completion : 설립일자
    • transaction_year_month : 거래년월
    • transaction_date : 거래날짜
    • floor : 층
    • transaction_real_price : 실거래가 (target variable)
    In [7]:
    train_null = train.drop('transaction_real_price', axis = 1).isnull().sum()/len(train)*100
    test_null = test.isnull().sum()/len(test)*100
    pd.DataFrame({'train_null_count' : train_null, 'test_null_count' : test_null})
    
    Out[7]:
    train_null_count test_null_count
    transaction_id 0.0 0.0
    apartment_id 0.0 0.0
    city 0.0 0.0
    dong 0.0 0.0
    jibun 0.0 0.0
    apt 0.0 0.0
    addr_kr 0.0 0.0
    exclusive_use_area 0.0 0.0
    year_of_completion 0.0 0.0
    transaction_year_month 0.0 0.0
    transaction_date 0.0 0.0
    floor 0.0 0.0
    In [8]:
    train.head()
    
    Out[8]:
    transaction_id apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price
    0 0 7622 서울특별시 신교동 6-13 신현(101동) 신교동 6-13 신현(101동) 84.82 2002 200801 21~31 2 37500
    1 1 5399 서울특별시 필운동 142 사직파크맨션 필운동 142 사직파크맨션 99.17 1973 200801 1~10 6 20000
    2 2 3578 서울특별시 필운동 174-1 두레엘리시안 필운동 174-1 두레엘리시안 84.74 2007 200801 1~10 6 38500
    3 3 10957 서울특별시 내수동 95 파크팰리스 내수동 95 파크팰리스 146.39 2003 200801 11~20 15 118000
    4 4 10639 서울특별시 내수동 110-15 킹스매너 내수동 110-15 킹스매너 194.43 2004 200801 21~31 3 120000

    2. Exploratory Data Analysis AND Processing

    2.1 Target Variable (Dependent Variable)

    transaction_real_price : 실거래가

    In [10]:
    train['transaction_real_price'].describe()
    
    Out[10]:
    count    1.216553e+06
    mean     3.822769e+04
    std      3.104898e+04
    min      1.000000e+02
    25%      1.900000e+04
    50%      3.090000e+04
    75%      4.700000e+04
    max      8.200000e+05
    Name: transaction_real_price, dtype: float64
    • 총 1216553개의 데이터, 약 120만개
    • 평균 : 38227.69
    • 표준편차 : 31048.98
    • min : 100
    • max : 820000, 82만
    In [11]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.distplot(train['transaction_real_price'])
    print("%s -> Skewness: %f, Kurtosis: %f" %  ('transaction_real_price',train['transaction_real_price'].skew(), 
                                                         train['transaction_real_price'].kurt()))
    
    transaction_real_price -> Skewness: 3.407169, Kurtosis: 24.839821
    
    • 왜도(Skewness) : 왼쪽으로 치우쳐져 있을수록 값이크고, 오른쪽으로 치우쳐져 있을 수록 값이 작아진다. 즉, 0에 가까울수록 좋은 형태
    • 첨도(Kurtosis) : 첨도 값이 3에 가까울 경우 정규분포에 가까우며, 첨도 값이 클수록 뾰족하고 값이 작을 수록 완만해진다
    In [12]:
    train['transaction_real_price'] = np.log1p(train['transaction_real_price'])
    print("%s -> Skewness: %f, Kurtosis: %f" %  ('transaction_real_price',train['transaction_real_price'].skew(), 
                                                         train['transaction_real_price'].kurt()))
    
    transaction_real_price -> Skewness: -0.094932, Kurtosis: 0.248866
    
    In [13]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.distplot(train['transaction_real_price'])
    
    Out[13]:
    <matplotlib.axes._subplots.AxesSubplot at 0x1ed3653efd0>

    columns 상관관계

    In [14]:
    #상관관계 확인
    k=train.shape[1] #히트맵 변수 갯수
    corrmat = train.corr() #변수간의 상관관계
    cols = corrmat.nlargest(k, 'transaction_real_price')['transaction_real_price'].index #price기준으로 제일 큰순서대로 20개를 뽑아냄
    cm = np.corrcoef(train[cols].values.T)
    f, ax = plt.subplots(figsize=(8, 6))
    sns.heatmap(data = cm, annot=True, square=True, fmt = '.2f', linewidths=.5, cmap='Reds', 
                yticklabels = cols.values, xticklabels = cols.values)
    
    Out[14]:
    <matplotlib.axes._subplots.AxesSubplot at 0x1ed367416a0>

    2.2 Numeric Variable

    transaction_id & apartment_id : 거래 id & 아파트 id

    In [15]:
    len(train['apartment_id'].unique())
    
    Out[15]:
    12533

    transaction_id는 예측을 하는 데 필요없고, apartment_id는 unique로 갯수를 확인해 보니 12533개로 겹치는 부분이 상당히 많은 것을 알 수 있습니다.

    transaction_id가 순서가 섞여있지만, 나중에 문제될 것이 없습니다.

    따라서, transaction_id는 삭제를 하고, apartment_id는 그대로 놔두겠습니다.

    In [16]:
    train_id = train['transaction_id']
    train = train.drop('transaction_id', axis=1)
    test_id = test['transaction_id']
    test = test.drop('transaction_id', axis=1)
    

    floor : 층

    In [17]:
    #약 100만개의 데이터라 sns.regplot 사용 시 엄청 오래걸림...
    f, ax = plt.subplots(figsize = (8,6))
    plt.scatter(train['floor'], train['transaction_real_price'])
    plt.xlabel('floor')
    plt.ylabel('transaction_real_price')
    plt.show()
    
    In [19]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.distplot(train['floor'])
    print("%s -> Skewness: %f, Kurtosis: %f" %  ('floor',train['floor'].skew(), 
                                                         train['floor'].kurt()))
    
    floor -> Skewness: 1.324710, Kurtosis: 3.796603
    

    대부분의 데이터는 다른데이터와 비교하기 위해 왜도, 첨도 조정은 마지막에 한다.

    exclusive_use_area : 전용 면적

    In [20]:
    train['exclusive_use_area'].describe()
    
    Out[20]:
    count    1.216553e+06
    mean     7.816549e+01
    std      2.915113e+01
    min      9.260000e+00
    25%      5.976000e+01
    50%      8.241000e+01
    75%      8.497000e+01
    max      4.243200e+02
    Name: exclusive_use_area, dtype: float64
    • 평균 : 78.16549
    • 표준편차 : 29.15113
    • min : 9.26
    • max : 424.32

    float형식으로 나타나있음. 면적의 단위는 m^2

    In [21]:
    #약 100만개의 데이터라 sns.regplot 사용 시 엄청 오래걸림...
    f, ax = plt.subplots(figsize = (8,6))
    plt.scatter(train['exclusive_use_area'], train['transaction_real_price'])
    plt.xlabel('exclusive_use_area')
    plt.ylabel('transaction_real_price')
    plt.show()
    

    많이 벗어나 보이는 이상치들을 탐색해보겠습니다.

    In [22]:
    train[train['exclusive_use_area']>400]
    
    Out[22]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price
    563870 12633 서울특별시 도곡동 193-1 힐데스하임빌라 도곡동 193-1 힐데스하임빌라 424.32 1998 201604 11~20 10 13.118357
    In [23]:
    train[(train['exclusive_use_area']<150)&(train['transaction_real_price']<6)]
    
    Out[23]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price
    312119 10853 서울특별시 신월동 128 태헌(신월프라자) 신월동 128 태헌(신월프라자) 56.97 1999 201005 21~31 7 5.860786
    722888 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 138.25 1974 201606 21~30 -1 4.615121

    딱히 이상이 없어 보임

    In [24]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.distplot(train['exclusive_use_area'])
    print("%s -> Skewness: %f, Kurtosis: %f" %  ('exclusive_use_area',train['exclusive_use_area'].skew(), 
                                                         train['exclusive_use_area'].kurt()))
    
    exclusive_use_area -> Skewness: 1.227509, Kurtosis: 3.100517
    

    transaction_year_month : 거래 년, 월

    In [25]:
    train_test_data = [train, test]
    
    for dataset in train_test_data:
        #date -> 년, 월 단위로 새로운 칼럼 만듦
        dataset['transaction_year_month'] = dataset['transaction_year_month'].astype(str)
        dataset['year'] = dataset['transaction_year_month'].str[:4].astype(int)
        dataset['month'] = dataset['transaction_year_month'].str[4:6].astype(int)
        dataset['transaction_year_month'] = dataset['transaction_year_month'].astype(int)
    
    In [26]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.boxplot(train['year'], train['transaction_real_price'])
    plt.show()
    
    In [27]:
    train[(train['year']==2016) & (train['transaction_real_price']<6)]
    
    Out[27]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month
    722888 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 138.25 1974 201606 21~30 -1 4.615121 2016 6

    서면아파트가 왜이렇게 값이 낮을까 다른 아파트는 어떨지..

    In [28]:
    train[train['apt']=='서면']
    
    Out[28]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month
    695725 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201105 21~31 3 8.682877 2011 5
    696834 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201108 21~31 1 8.922792 2011 8
    700884 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 88.93 1974 201206 1~10 1 10.126671 2012 6
    702589 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201212 21~31 5 8.699681 2012 12
    702876 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201301 11~20 4 8.909370 2013 1
    703979 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201304 1~10 1 8.853808 2013 4
    711024 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201407 21~31 5 8.853808 2014 7
    712441 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201410 21~31 3 9.082621 2014 10
    713864 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201501 1~10 4 8.955577 2015 1
    721684 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201604 1~10 1 9.059634 2016 4
    722888 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 138.25 1974 201606 21~30 -1 4.615121 2016 6
    723957 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 55.04 1974 201608 21~31 2 10.051951 2016 8
    726597 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201612 11~20 4 8.802522 2016 12
    1186983 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 34.08 1974 201702 11~20 1 9.705098 2017 2
    1189112 6238 부산광역시 전포동 산99-46 서면 전포동 산99-46 서면 57.59 1976 201706 21~30 3 9.137877 2017 6
    1189212 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 54.15 1974 201706 1~10 5 10.173553 2017 6

    floor가 -1인 경우 가격이 현저히 낮음, 다른 -1층은?

    In [29]:
    train[train['floor']==-1].sort_values('transaction_real_price')
    
    Out[29]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month
    722888 6225 부산광역시 범전동 263-5 서면 범전동 263-5 서면 138.250 1974 201606 21~30 -1 4.615121 2016 6
    651052 1514 부산광역시 대청동4가 75-176 근영빌라2동 대청동4가 75-176 근영빌라2동 47.170 1996 200809 21~30 -1 7.170888 2008 9
    651087 1513 부산광역시 대청동4가 75-181 근영빌라1동 대청동4가 75-181 근영빌라1동 59.890 1996 200810 11~20 -1 7.824446 2008 10
    651641 1514 부산광역시 대청동4가 75-176 근영빌라2동 대청동4가 75-176 근영빌라2동 47.170 1996 201101 21~31 -1 8.071219 2011 1
    674249 9764 부산광역시 동삼동 213-19 조은아크로빌 동삼동 213-19 조은아크로빌 46.800 2001 201506 11~20 -1 8.160804 2015 6
    652044 1516 부산광역시 대청동4가 75-167 근영빌라4동 대청동4가 75-167 근영빌라4동 46.650 1996 201211 1~10 -1 8.343078 2012 11
    664479 1853 부산광역시 초량동 89-6 남도 초량동 89-6 남도 76.530 1975 201606 21~30 -1 8.366603 2016 6
    9602 9058 서울특별시 신당동 432-1970 유정 신당동 432-1970 유정 29.400 2001 201502 11~20 -1 8.412055 2015 2
    267272 1269 서울특별시 홍은동 277-145 교수(A) 홍은동 277-145 교수(A) 100.440 2006 201012 1~10 -1 8.434029 2010 12
    698094 7163 부산광역시 개금동 627-1 시영 개금동 627-1 시영 39.670 1975 201110 1~10 -1 8.434029 2011 10
    698128 7163 부산광역시 개금동 627-1 시영 개금동 627-1 시영 39.670 1975 201110 11~20 -1 8.455531 2011 10
    129497 7898 서울특별시 안암동4가 23-3 안암 안암동4가 23-3 안암 36.100 1969 201603 21~31 -1 8.853808 2016 3
    1190044 7401 부산광역시 부암동 669-6 신서면 부암동 669-6 신서면 89.420 1973 201708 1~10 -1 8.853808 2017 8
    5172 7023 서울특별시 신당동 432-2006 수산타운(2차) 신당동 432-2006 수산타운(2차) 32.860 2001 200803 1~10 -1 8.853808 2008 3
    658546 4529 부산광역시 남부민동 30-1 문화 남부민동 30-1 문화 61.750 1975 201504 21~30 -1 9.082621 2015 4
    664089 1853 부산광역시 초량동 89-6 남도 초량동 89-6 남도 175.900 1975 201509 21~30 -1 9.105091 2015 9
    264037 8221 서울특별시 연희동 196-1 연희궁 연희동 196-1 연희궁 165.290 1972 200805 1~10 -1 9.159152 2008 5
    5113 9058 서울특별시 신당동 432-1970 유정 신당동 432-1970 유정 59.650 2001 200802 11~20 -1 9.190240 2008 2
    9739 396 서울특별시 신당동 432-806 GV 신당동 432-806 GV 37.490 2000 201503 21~31 -1 9.210440 2015 3
    129496 7898 서울특별시 안암동4가 23-3 안암 안암동4가 23-3 안암 52.890 1969 201603 21~31 -1 9.305741 2016 3
    418950 2298 서울특별시 시흥동 989-11 대도훼미리 시흥동 989-11 대도훼미리 57.690 1991 201612 21~31 -1 9.392745 2016 12
    410450 2298 서울특별시 시흥동 989-11 대도훼미리 시흥동 989-11 대도훼미리 57.690 1991 201003 11~20 -1 9.392745 2010 3
    5240 43 서울특별시 신당동 432-2001 (432-2001) 신당동 432-2001 (432-2001) 49.780 2001 200804 1~10 -1 9.417436 2008 4
    358581 4650 서울특별시 화곡동 46-212 밀레니엄 화곡동 46-212 밀레니엄 59.740 2000 201409 1~10 -1 9.433564 2014 9
    6582 11223 서울특별시 신당동 432-1956 하영 신당동 432-1956 하영 35.750 2002 201011 1~10 -1 9.488048 2010 11
    21492 11393 서울특별시 한남동 29-4 한성1 한남동 29-4 한성1 24.760 1974 201603 1~10 -1 9.493336 2016 3
    356867 10390 서울특별시 화곡동 457-1 청송평화 화곡동 457-1 청송평화 63.210 2006 201404 11~20 -1 9.510519 2014 4
    6209 2116 서울특별시 신당동 432-1982 다다 신당동 432-1982 다다 59.950 2000 200911 21~30 -1 9.532496 2009 11
    477336 597 서울특별시 신림동 1644 강남 신림동 1644 강남 47.900 1974 201104 11~20 -1 9.541154 2011 4
    6612 7458 서울특별시 신당동 432-1972 신신(1차) 신당동 432-1972 신신(1차) 38.930 2001 201011 11~20 -1 9.546884 2010 11
    ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
    245995 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 101.490 2010 201007 11~20 -1 10.900455 2010 7
    250061 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.750 2010 201211 11~20 -1 10.942598 2012 11
    253920 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 101.490 2010 201406 1~10 -1 10.973375 2014 6
    250074 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.750 2010 201211 21~30 -1 10.990128 2012 11
    257066 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 101.970 2010 201505 1~10 -1 11.000448 2015 5
    248055 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.480 2010 201106 1~10 -1 11.000832 2011 6
    248612 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 101.490 2010 201110 1~10 -1 11.038126 2011 10
    250719 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.480 2010 201303 1~10 -1 11.042938 2013 3
    246431 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.560 2010 201010 1~10 -1 11.176347 2010 10
    21792 10810 서울특별시 효창동 5-1 태원팰리스 효창동 5-1 태원팰리스 177.120 2007 201605 21~31 -1 11.184435 2016 5
    1128345 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.480 2010 201704 1~10 -1 11.211834 2017 4
    247949 9125 서울특별시 진관동 84 은평뉴타운 우물골(두산위브7단지) 진관동 84 은평뉴타운 우물골(두산위브7단지) 134.480 2010 201105 21~31 -1 11.215651 2011 5
    13289 3913 서울특별시 원효로1가 17-5 로얄카운티-2 원효로1가 17-5 로얄카운티-2 133.350 2006 200904 21~30 -1 11.225257 2009 4
    13581 3913 서울특별시 원효로1가 17-5 로얄카운티-2 원효로1가 17-5 로얄카운티-2 133.350 2006 200906 21~30 -1 11.245059 2009 6
    503489 2004 서울특별시 방배동 802-8 노블씨티 방배동 802-8 노블씨티 97.360 2008 201106 11~20 -1 11.264477 2011 6
    1094566 11280 서울특별시 보광동 208-1 한강빌라 보광동 208-1 한강빌라 132.130 2001 201702 21~28 -1 11.338584 2017 2
    13693 2006 서울특별시 동빙고동 310-10 노블캐슬 동빙고동 310-10 노블캐슬 165.760 2008 200906 1~10 -1 11.379588 2009 6
    502820 2004 서울특별시 방배동 802-8 노블씨티 방배동 802-8 노블씨티 114.160 2008 201103 21~31 -1 11.402005 2011 3
    519130 2004 서울특별시 방배동 802-8 노블씨티 방배동 802-8 노블씨티 114.160 2008 201510 11~20 -1 11.487618 2015 10
    13819 2006 서울특별시 동빙고동 310-10 노블캐슬 동빙고동 310-10 노블캐슬 165.680 2008 200907 1~10 -1 11.608245 2009 7
    15759 10911 서울특별시 한남동 26-5 트윈빌 에이동 한남동 26-5 트윈빌 에이동 196.690 2008 201110 1~10 -1 11.608245 2011 10
    531719 7105 서울특별시 논현동 55 스위트캐슬레지던스 논현동 55 스위트캐슬레지던스 209.370 2004 200907 11~20 -1 11.652696 2009 7
    23382 10910 서울특별시 한남동 26-10 트윈빌 비동 한남동 26-10 트윈빌 비동 176.730 2008 201610 21~31 -1 11.870607 2016 10
    12963 2006 서울특별시 동빙고동 310-10 노블캐슬 동빙고동 310-10 노블캐슬 165.680 2008 200810 1~10 -1 11.951187 2008 10
    542431 10309 서울특별시 청담동 102-1 청담파라곤Ⅱ 1단지 청담동 102-1 청담파라곤Ⅱ 1단지 217.200 2010 201204 21~30 -1 12.283038 2012 4
    537384 10310 서울특별시 청담동 102-13 청담파라곤Ⅱ 2단지 청담동 102-13 청담파라곤Ⅱ 2단지 241.880 2010 201012 11~20 -1 12.577640 2010 12
    1095417 11320 서울특별시 한남동 810 한남더힐 한남동 810 한남더힐 212.524 2011 201705 21~31 -1 13.081543 2017 5
    1095416 11320 서울특별시 한남동 810 한남더힐 한남동 810 한남더힐 212.524 2011 201705 21~31 -1 13.102163 2017 5
    23585 11320 서울특별시 한남동 810 한남더힐 한남동 810 한남더힐 240.230 2011 201612 1~10 -1 13.204866 2016 12
    23376 11320 서울특별시 한남동 810 한남더힐 한남동 810 한남더힐 240.230 2011 201610 11~20 -1 13.262127 2016 10

    140 rows × 14 columns

    -1 치고 가격이 높은 경우도 있음

    같은 아파트에서는 floor가 -1인 경우의 영향을 확인해봄

    In [30]:
    train[train['apt']=='근영빌라1동'].sort_values('floor')
    
    Out[30]:
    apartment_id city dong jibun apt addr_kr exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month
    651087 1513 부산광역시 대청동4가 75-181 근영빌라1동 대청동4가 75-181 근영빌라1동 59.89 1996 200810 11~20 -1 7.824446 2008 10
    651599 1513 부산광역시 대청동4가 75-181 근영빌라1동 대청동4가 75-181 근영빌라1동 54.73 1996 201011 1~10 1 8.216358 2010 11
    652009 1513 부산광역시 대청동4가 75-181 근영빌라1동 대청동4가 75-181 근영빌라1동 51.83 1996 201210 21~31 5 8.824825 2012 10
    652591 1513 부산광역시 대청동4가 75-181 근영빌라1동 대청동4가 75-181 근영빌라1동 59.89 1996 201508 1~10 5 9.169623 2015 8

    대충확인했을 때 아파트에 따라 다름.

    따라서, 이상치라고 판단하기 어려워 삭제하지 않는다.

    In [31]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.boxplot(train['month'], train['transaction_real_price'])
    plt.show()
    

    year_of_completion : 설립일자

    In [32]:
    f, ax = plt.subplots(figsize = (22,6))
    sns.boxplot(train['year_of_completion'], train['transaction_real_price'])
    plt.show()
    

    이상치를 찾을 수 ㅇ벗..

    2.3 Catergorical Variable

    city : 도시

    In [33]:
    replace_name = {'서울특별시' : 0, '부산광역시' : 1 }
    train = train.replace({'city' : replace_name})
    test = test.replace({'city' : replace_name})
    
    In [34]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.boxplot(train['city'], train['transaction_real_price'])
    plt.show()
    
    In [35]:
    f, ax = plt.subplots(figsize = (8,6))
    sns.countplot(train['city'])
    plt.show()
    

    addr_kr : 주소

    동, 지번, 아파트단지이름을 합친 것을 addr_kr로 하였으므로 그냥 삭제 하겠습니다.

    In [36]:
    train = train.drop('addr_kr', axis=1)
    test = test.drop('addr_kr', axis=1)
    

    dong

    데이콘 튜토리얼 샘플코드에서 한강의 유무에 따른 feature를 하나 생성 해준다.

    In [39]:
    train['hangang']=train['dong'].isin(['성수동1가','삼성동','이촌동','공덕동','서교동','한강로3가','목동']).astype(int)
    test['hangang']=test['dong'].isin(['성수동1가','삼성동','이촌동','공덕동','서교동','한강로3가','목동']).astype(int)
    
    In [37]:
    len(train['dong'].unique())
    
    Out[37]:
    473

    dong은 그 지역을 그룹화 한 것으로 지역에 따라 가격차이를 보여줄 수 있으므로,

    아파트 실거래가의 평균순으로 데이터를 labeling 한다.

    In [38]:
    train_dong = train[['transaction_real_price','dong']].groupby('dong').mean().sort_values('transaction_real_price').reset_index()
    train_dong.head()
    
    Out[38]:
    dong transaction_real_price
    0 신선동3가 8.543619
    1 봉래동5가 8.590871
    2 장안읍 명례리 8.597728
    3 신창동2가 8.601466
    4 신선동2가 8.622581
    In [40]:
    dong_num = {}
    for i in range(len(train_dong)):
        dong = train_dong['dong'].iloc[i]
        dong_num[dong] = i
        
    dong_num
    
    Out[40]:
    {'신선동3가': 0,
     '봉래동5가': 1,
     '장안읍 명례리': 2,
     '신창동2가': 3,
     '신선동2가': 4,
     '보수동1가': 5,
     '장충동2가': 6,
     '중앙동4가': 7,
     '부평동2가': 8,
     '수정동': 9,
     '필동1가': 10,
     '아미동2가': 11,
     '동광동5가': 12,
     '기장읍 대변리': 13,
     '초장동': 14,
     '남항동3가': 15,
     '대청동1가': 16,
     '기장읍 서부리': 17,
     '동삼동': 18,
     '반송동': 19,
     '보수동2가': 20,
     '누상동': 21,
     '봉래동3가': 22,
     '대청동4가': 23,
     '서동': 24,
     '일광면 이천리': 25,
     '덕천동': 26,
     '일광면 삼성리': 27,
     '봉래동4가': 28,
     '감만동': 29,
     '영등포동3가': 30,
     '모라동': 31,
     '행촌동': 32,
     '동대신동3가': 33,
     '학장동': 34,
     '구평동': 35,
     '좌천동': 36,
     '금곡동': 37,
     '영주동': 38,
     '장림동': 39,
     '토성동2가': 40,
     '기장읍 청강리': 41,
     '기장읍 대라리': 42,
     '영등포동1가': 43,
     '영등포동2가': 44,
     '미근동': 45,
     '감천동': 46,
     '감전동': 47,
     '전포동': 48,
     '금사동': 49,
     '기장읍 동부리': 50,
     '칠산동': 51,
     '덕포동': 52,
     '초량동': 53,
     '명장동': 54,
     '다대동': 55,
     '서대신동1가': 56,
     '오장동': 57,
     '기장읍 교리': 58,
     '대창동1가': 59,
     '영등포동4가': 60,
     '회동동': 61,
     '신평동': 62,
     '범천동': 63,
     '우암동': 64,
     '구포동': 65,
     '괴정동': 66,
     '당감동': 67,
     '안암동4가': 68,
     '토성동5가': 69,
     '개금동': 70,
     '남산동': 71,
     '당리동': 72,
     '당산동6가': 73,
     '주례동': 74,
     '통인동': 75,
     '청학동': 76,
     '충무동2가': 77,
     '암남동': 78,
     '엄궁동': 79,
     '만덕동': 80,
     '영선동4가': 81,
     '남부민동': 82,
     '성북동': 83,
     '광안동': 84,
     '하단동': 85,
     '삼락동': 86,
     '지사동': 87,
     '수안동': 88,
     '충신동': 89,
     '대평동1가': 90,
     '보수동3가': 91,
     '초읍동': 92,
     '봉래동1가': 93,
     '가야동': 94,
     '재송동': 95,
     '동대신동1가': 96,
     '영선동3가': 97,
     '정관읍 달산리': 98,
     '서대신동2가': 99,
     '대연동': 100,
     '부용동1가': 101,
     '정관읍 방곡리': 102,
     '장안읍 좌천리': 103,
     '동숭동': 104,
     '반여동': 105,
     '연건동': 106,
     '문현동': 107,
     '용당동': 108,
     '안암동3가': 109,
     '남창동': 110,
     '부전동': 111,
     '대조동': 112,
     '청룡동': 113,
     '부곡동': 114,
     '괘법동': 115,
     '연산동': 116,
     '신호동': 117,
     '범전동': 118,
     '인현동2가': 119,
     '효제동': 120,
     '부민동1가': 121,
     '남항동2가': 122,
     '토성동3가': 123,
     '부평동4가': 124,
     '명륜3가': 125,
     '영선동1가': 126,
     '신창동1가': 127,
     '녹산동': 128,
     '노고산동': 129,
     '온천동': 130,
     '남항동1가': 131,
     '화명동': 132,
     '안락동': 133,
     '망미동': 134,
     '만리동2가': 135,
     '낙민동': 136,
     '대교동2가': 137,
     '서대신동3가': 138,
     '양정동': 139,
     '부민동3가': 140,
     '복천동': 141,
     '연지동': 142,
     '부암동': 143,
     '구서동': 144,
     '익선동': 145,
     '좌동': 146,
     '송정동': 147,
     '정관읍 매학리': 148,
     '원효로2가': 149,
     '동소문동6가': 150,
     '영등포동5가': 151,
     '쌍문동': 152,
     '동대신동2가': 153,
     '원효로3가': 154,
     '봉래동2가': 155,
     '사직동': 156,
     '삼선동5가': 157,
     '묵정동': 158,
     '가리봉동': 159,
     '기장읍 내리': 160,
     '용호동': 161,
     '거제동': 162,
     '신설동': 163,
     '대청동2가': 164,
     '철마면 고촌리': 165,
     '범일동': 166,
     '가산동': 167,
     '수영동': 168,
     '갈현동': 169,
     '정관읍 모전리': 170,
     '화양동': 171,
     '상계동': 172,
     '충무로5가': 173,
     '낙원동': 174,
     '신월동': 175,
     '장전동': 176,
     '신영동': 177,
     '수유동': 178,
     '월계동': 179,
     '영선동2가': 180,
     '번동': 181,
     '독산동': 182,
     '토성동1가': 183,
     '정관읍 용수리': 184,
     '도봉동': 185,
     '중동': 186,
     '동선동4가': 187,
     '창천동': 188,
     '창동': 189,
     '방학동': 190,
     '구산동': 191,
     '공릉동': 192,
     '신내동': 193,
     '구로동': 194,
     '대저1동': 195,
     '망우동': 196,
     '당산동2가': 197,
     '시흥동': 198,
     '오류동': 199,
     '중곡동': 200,
     '면목동': 201,
     '방화동': 202,
     '상도1동': 203,
     '궁동': 204,
     '이화동': 205,
     '산림동': 206,
     '문래동2가': 207,
     '역촌동': 208,
     '중화동': 209,
     '가양동': 210,
     '민락동': 211,
     '보문동6가': 212,
     '양평동2가': 213,
     '하계동': 214,
     '남천동': 215,
     '중계동': 216,
     '보문동2가': 217,
     '충정로3가': 218,
     '신림동': 219,
     '동소문동4가': 220,
     '회기동': 221,
     '고척동': 222,
     '정릉동': 223,
     '문래동6가': 224,
     '신사동': 225,
     '삼전동': 226,
     '우이동': 227,
     '숭인동': 228,
     '증산동': 229,
     '사근동': 230,
     '묵동': 231,
     '연희동': 232,
     '능동': 233,
     '창신동': 234,
     '홍은동': 235,
     '홍익동': 236,
     '마포동': 237,
     '상월곡동': 238,
     '예장동': 239,
     '명지동': 240,
     '수송동': 241,
     '개봉동': 242,
     '길동': 243,
     '항동': 244,
     '양평동1가': 245,
     '휘경동': 246,
     '양평동6가': 247,
     '상봉동': 248,
     '대림동': 249,
     '남산동2가': 250,
     '녹번동': 251,
     '영등포동7가': 252,
     '홍제동': 253,
     '명륜동': 254,
     '청파동1가': 255,
     '천호동': 256,
     '문래동5가': 257,
     '응암동': 258,
     '동선동5가': 259,
     '답십리동': 260,
     '등촌동': 261,
     '신길동': 262,
     '수색동': 263,
     '천연동': 264,
     '동선동3가': 265,
     '화곡동': 266,
     '미아동': 267,
     '용답동': 268,
     '석관동': 269,
     '명륜1가': 270,
     '제기동': 271,
     '돈암동': 272,
     '양평동4가': 273,
     '충무동1가': 274,
     '성내동': 275,
     '장안동': 276,
     '우동': 277,
     '장위동': 278,
     '공항동': 279,
     '교북동': 280,
     '거여동': 281,
     '봉천동': 282,
     '이문동': 283,
     '양평동5가': 284,
     '삼선동4가': 285,
     '망원동': 286,
     '을지로5가': 287,
     '충정로2가': 288,
     '대현동': 289,
     '불광동': 290,
     '마장동': 291,
     '염창동': 292,
     '종암동': 293,
     '전농동': 294,
     '온수동': 295,
     '연남동': 296,
     '용두동': 297,
     '당산동1가': 298,
     '도림동': 299,
     '문래동4가': 300,
     '양평동3가': 301,
     '천왕동': 302,
     '성산동': 303,
     '내발산동': 304,
     '하월곡동': 305,
     '북아현동': 306,
     '청량리동': 307,
     '안암동1가': 308,
     '동소문동7가': 309,
     '당산동': 310,
     '강일동': 311,
     '노량진동': 312,
     '영등포동': 313,
     '삼선동2가': 314,
     '마천동': 315,
     '군자동': 316,
     '남현동': 317,
     '성북동1가': 318,
     '길음동': 319,
     '청파동3가': 320,
     '구수동': 321,
     '현저동': 322,
     '필동3가': 323,
     '남가좌동': 324,
     '영등포동8가': 325,
     '혜화동': 326,
     '구기동': 327,
     '대방동': 328,
     '풍납동': 329,
     '북가좌동': 330,
     '보문동3가': 331,
     '금호동1가': 332,
     '도선동': 333,
     '하왕십리동': 334,
     '대교동1가': 335,
     '신도림동': 336,
     '신수동': 337,
     '순화동': 338,
     '당산동3가': 339,
     '정동': 340,
     '명일동': 341,
     '신정동': 342,
     '신문로1가': 343,
     '용산동2가': 344,
     '영천동': 345,
     '사당동': 346,
     '산천동': 347,
     '보문동4가': 348,
     '응봉동': 349,
     '염리동': 350,
     '신교동': 351,
     '당산동4가': 352,
     '신창동': 353,
     '후암동': 354,
     '금호동3가': 355,
     '신대방동': 356,
     '황학동': 357,
     '도화동': 358,
     '토정동': 359,
     '신당동': 360,
     '본동': 361,
     '갈월동': 362,
     '당주동': 363,
     '충무로4가': 364,
     '상일동': 365,
     '합정동': 366,
     '효창동': 367,
     '행당동': 368,
     '대흥동': 369,
     '암사동': 370,
     '동소문동5가': 371,
     '명륜2가': 372,
     '진관동': 373,
     '동교동': 374,
     '오금동': 375,
     '동선동1가': 376,
     '양재동': 377,
     '평창동': 378,
     '도원동': 379,
     '수서동': 380,
     '마곡동': 381,
     '창전동': 382,
     '냉천동': 383,
     '상도동': 384,
     '삼선동3가': 385,
     '석촌동': 386,
     '구의동': 387,
     '고덕동': 388,
     '인의동': 389,
     '합동': 390,
     '가락동': 391,
     '만리동1가': 392,
     '자양동': 393,
     '중림동': 394,
     '용문동': 395,
     '문배동': 396,
     '신공덕동': 397,
     '문정동': 398,
     '성수동2가': 399,
     '성수동1가': 400,
     '공덕동': 401,
     '한강로2가': 402,
     '현석동': 403,
     '금호동4가': 404,
     '원효로4가': 405,
     '당산동5가': 406,
     '문래동3가': 407,
     '둔촌동': 408,
     '장지동': 409,
     '무악동': 410,
     '역삼동': 411,
     '상암동': 412,
     '논현동': 413,
     '필운동': 414,
     '광장동': 415,
     '흑석동': 416,
     '옥수동': 417,
     '흥인동': 418,
     '목동': 419,
     '송파동': 420,
     '용강동': 421,
     '청운동': 422,
     '아현동': 423,
     '서교동': 424,
     '보광동': 425,
     '금호동2가': 426,
     '동작동': 427,
     '옥인동': 428,
     '우면동': 429,
     '세곡동': 430,
     '이태원동': 431,
     '개포동': 432,
     '서초동': 433,
     '방이동': 434,
     '일원동': 435,
     '율현동': 436,
     '신원동': 437,
     '상수동': 438,
     '한강로1가': 439,
     '상왕십리동': 440,
     '한남동': 441,
     '방배동': 442,
     '내곡동': 443,
     '원효로1가': 444,
     '한강로3가': 445,
     '회현동1가': 446,
     '잠원동': 447,
     '신천동': 448,
     '이촌동': 449,
     '자곡동': 450,
     '신계동': 451,
     '삼성동': 452,
     '견지동': 453,
     '동자동': 454,
     '여의도동': 455,
     '도곡동': 456,
     '동빙고동': 457,
     '청담동': 458,
     '잠실동': 459,
     '하중동': 460,
     '대치동': 461,
     '내수동': 462,
     '주성동': 463,
     '서빙고동': 464,
     '교남동': 465,
     '남대문로5가': 466,
     '반포동': 467,
     '회현동2가': 468,
     '용산동5가': 469,
     '압구정동': 470,
     '청암동': 471,
     '장충동1가': 472}
    In [41]:
    train = train.replace({'dong' : dong_num})
    test = test.replace({'dong' : dong_num})
    train.head()
    
    Out[41]:
    apartment_id city dong jibun apt exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month hangang
    0 7622 0 351 6-13 신현(101동) 84.82 2002 200801 21~31 2 10.532123 2008 1 0
    1 5399 0 414 142 사직파크맨션 99.17 1973 200801 1~10 6 9.903538 2008 1 0
    2 3578 0 414 174-1 두레엘리시안 84.74 2007 200801 1~10 6 10.558439 2008 1 0
    3 10957 0 462 95 파크팰리스 146.39 2003 200801 11~20 15 11.678448 2008 1 0
    4 10639 0 462 110-15 킹스매너 194.43 2004 200801 21~31 3 11.695255 2008 1 0

    Jibun

    In [62]:
    len(train['jibun'].unique())
    
    Out[62]:
    8961
    In [63]:
    train_jibun = train[['transaction_real_price','jibun']].groupby('jibun').mean().sort_values('transaction_real_price').reset_index()
    train_jibun.head()
    
    Out[63]:
    jibun transaction_real_price
    0 산3-148 7.225286
    1 737-1 7.494417
    2 741-1 7.498174
    3 1181-4 7.585491
    4 11-174 7.601402

    apt

    In [42]:
    len(train['apt'].unique())
    
    Out[42]:
    10440
    In [43]:
    train_apt = train[['transaction_real_price','apt']].groupby('apt').mean().sort_values('transaction_real_price').reset_index()
    train_apt.head()
    
    Out[43]:
    apt transaction_real_price
    0 좌천시민(737-1) 7.494417
    1 좌천시민(741-1) 7.498174
    2 수정(1181-4) 7.585491
    3 수정(1175-1) 7.626830
    4 수정(1186-1) 7.685623

    지번과 아파트 데이터는 unique가 많으므로 따로 labeling을 하지 않는다.

    transaction_date

    transaction_date는 거래기간으로 처음 거래시작한 day와 거래가 끝난 day의 차이를 컬럼으로 만들어 주겠습니다.

    In [44]:
    train['day_diff'] = train['transaction_date'].str.extract('(~\d+)')[0].str[1:].astype(int) - train['transaction_date'].str.extract('(\d+~)')[0].str[:-1].astype(int)
    test['day_diff'] = test['transaction_date'].str.extract('(~\d+)')[0].str[1:].astype(int) - test['transaction_date'].str.extract('(\d+~)')[0].str[:-1].astype(int)
    
    In [45]:
    len(train['transaction_date'].unique())
    
    Out[45]:
    6

    거래기간 feature도 unique 갯수가 몇개 없기 때문에 labeling을 하겠습니다.

    In [46]:
    train_date = train[['transaction_real_price','transaction_date']].groupby('transaction_date').mean().sort_values('transaction_real_price').reset_index()
    train_date.head()
    
    Out[46]:
    transaction_date transaction_real_price
    0 21~29 10.176453
    1 21~28 10.286294
    2 1~10 10.293390
    3 11~20 10.306731
    4 21~31 10.318796
    In [47]:
    date_num = {}
    for i in range(len(train_date)):
        date = train_date['transaction_date'].iloc[i]
        date_num[date] = i
        
    date_num
    
    Out[47]:
    {'21~29': 0, '21~28': 1, '1~10': 2, '11~20': 3, '21~31': 4, '21~30': 5}
    In [48]:
    train = train.replace({'transaction_date' : date_num})
    test = test.replace({'transaction_date' : date_num})
    train.head()
    
    Out[48]:
    apartment_id city dong jibun apt exclusive_use_area year_of_completion transaction_year_month transaction_date floor transaction_real_price year month hangang day_diff
    0 7622 0 351 6-13 신현(101동) 84.82 2002 200801 4 2 10.532123 2008 1 0 10
    1 5399 0 414 142 사직파크맨션 99.17 1973 200801 2 6 9.903538 2008 1 0 9
    2 3578 0 414 174-1 두레엘리시안 84.74 2007 200801 2 6 10.558439 2008 1 0 9
    3 10957 0 462 95 파크팰리스 146.39 2003 200801 3 15 11.678448 2008 1 0 9
    4 10639 0 462 110-15 킹스매너 194.43 2004 200801 4 3 11.695255 2008 1 0 10

    2.4 Preprocessing

    floor 같은 경우 -값이 존재하기 때문에 log를 취하기 전에 각 값에 +5를 하면서 모든 값을 양수로 만들어줍니다.

    In [49]:
    train['floor'] = np.log(train['floor']+5)
    test['floor'] = np.log(test['floor']+5)
    f, ax = plt.subplots(figsize = (8,6))
    sns.distplot(train['floor'])
    print("%s -> Skewness: %f, Kurtosis: %f" %  ('floor',train['floor'].skew(), 
                                                         train['floor'].kurt()))
    
    floor -> Skewness: 0.089636, Kurtosis: -0.640885
    
    In [50]:
    drop_columns = ['apt', 'jibun', 'transaction_year_month']
    
    train = train.drop(drop_columns, axis=1)
    test = test.drop(drop_columns, axis=1)
    
    In [51]:
    train.head()
    
    Out[51]:
    apartment_id city dong exclusive_use_area year_of_completion transaction_date floor transaction_real_price year month hangang day_diff
    0 7622 0 351 84.82 2002 4 1.945910 10.532123 2008 1 0 10
    1 5399 0 414 99.17 1973 2 2.397895 9.903538 2008 1 0 9
    2 3578 0 414 84.74 2007 2 2.397895 10.558439 2008 1 0 9
    3 10957 0 462 146.39 2003 3 2.995732 11.678448 2008 1 0 9
    4 10639 0 462 194.43 2004 4 2.079442 11.695255 2008 1 0 10

    3. Feature Engineering

    In [52]:
    train_test_data = [train, test]
    
    for dataset in train_test_data:
        # 거래하는 기간까지의 아파트 나이를 feature 생성
        dataset['age'] = dataset['year'] - dataset['year_of_completion']
        # 샘플코드에 있는 아파트의 재건추 유무를 판단하는 feature 생성
        dataset['is_rebuild']=(dataset['age']>=30).astype(int)
    
    In [53]:
    train_columns = []
    for column in train.columns[:]:
        if train[column].skew() >= 1:
            print("%s -> Skewness: %f, Kurtosis: %f" %  (column,train[column].skew(), 
                                                     train[column].kurt()))
            train_columns.append(column)
        elif train[column].kurt() >= 3:
            print("%s -> Skewness: %f, Kurtosis: %f" %  (column,train[column].skew(), 
                                                     train[column].kurt()))
            train_columns.append(column)
    
    exclusive_use_area -> Skewness: 1.227509, Kurtosis: 3.100517
    hangang -> Skewness: 6.358349, Kurtosis: 38.428662
    day_diff -> Skewness: -0.589751, Kurtosis: 4.573129
    is_rebuild -> Skewness: 3.324832, Kurtosis: 9.054522
    
    In [54]:
    #정규분포모형을 가질 수 있도록 첨도와 왜도를 조정
    #조정하는 방법에는 square root, quarter root, log 등이 있다.
    #log에서 0의 값이 들어왔을 때 무한으로 가는 것을 방지하도록 1 더해주는 log1p를 사용
    
    for column in train_columns :
        train[column] = np.log1p(train[column])
        test[column] = np.log1p(test[column])
        print("%s -> Skewness: %f, Kurtosis: %f" %  (column,train[column].skew(), 
                                                     train[column].kurt()))
    
    exclusive_use_area -> Skewness: -0.438156, Kurtosis: 1.744119
    hangang -> Skewness: 6.358349, Kurtosis: 38.428662
    day_diff -> Skewness: -1.128137, Kurtosis: 6.788569
    is_rebuild -> Skewness: 3.324832, Kurtosis: 9.054522
    
    In [55]:
    #상관관계 확인
    k=train.shape[1] #히트맵 변수 갯수
    corrmat = train.corr() #변수간의 상관관계
    cols = corrmat.nlargest(k, 'transaction_real_price')['transaction_real_price'].index #price기준으로 제일 큰순서대로 20개를 뽑아냄
    cm = np.corrcoef(train[cols].values.T)
    f, ax = plt.subplots(figsize=(20, 6))
    sns.heatmap(data = cm, annot=True, square=True, fmt = '.2f', linewidths=.5, cmap='Reds', 
                yticklabels = cols.values, xticklabels = cols.values)
    
    Out[55]:
    <matplotlib.axes._subplots.AxesSubplot at 0x1ed57d70208>

    4. Modeling

    In [56]:
    from sklearn.linear_model import ElasticNet, Lasso
    from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
    from sklearn.kernel_ridge import KernelRidge
    from sklearn.pipeline import make_pipeline
    from sklearn.preprocessing import RobustScaler
    from sklearn.model_selection import KFold, cross_val_score, train_test_split
    from sklearn.metrics import mean_squared_error
    import xgboost as xgb
    import lightgbm as lgb
    
    In [57]:
    target = train['transaction_real_price']
    del train['transaction_real_price']
    
    In [58]:
    #cross validation score
    n_folds = 2
    
    def cv_score(models):
        kfold = KFold(n_splits=n_folds, shuffle=True ,random_state=42).get_n_splits(train.values)
        for m in models:
            cvs = np.mean(cross_val_score(m['model'], train.values, target, cv=kfold))
            rmse = np.mean(np.sqrt(-cross_val_score(m['model'], train.values, np.expm1(target), scoring = "neg_mean_squared_error", cv = kfold)))
            print("Model {} CV score : {:.4f}".format(m['name'], cvs))
            print("RMSE : {:.4f}".format(rmse))
    
    In [59]:
    lasso = make_pipeline(RobustScaler(), Lasso(alpha = 0.0005, random_state=42))
    ENet = make_pipeline(RobustScaler(), ElasticNet(alpha=0.0005, l1_ratio=.9, random_state=42))
    gboost = GradientBoostingRegressor(random_state=42)
    forest = RandomForestRegressor(n_estimators = 100, n_jobs = -1, random_state=42)
    xgboost = xgb.XGBRegressor(random_state=42)
    lightgbm = lgb.LGBMRegressor(random_state=42, num_leaves = 100, min_data_in_leaf = 15, max_depth=6,
                                learning_rate = 0.1, min_child_samples = 30, feature_fraction=0.9, bagging_freq= 1,
                                bagging_fraction = 0.9, bagging_seed = 11, lambda_l1 = 0.1, verbosity = -1 )
    
    models = [{'model': gboost, 'name':'GradientBoosting'}, {'model': xgboost, 'name':'XGBoost'},
              {'model': lightgbm, 'name':'LightGBM'}, {'model' : lasso, 'name' : 'LASSO Regression'}, 
              {'model' : ENet, 'name' : 'Elastic Net Regression'}, {'model' : forest, 'name' : 'RandomForset'}]
    
    In [60]:
    start = timeit.default_timer()
    cv_score(models)
    stop = timeit.default_timer()
    print('불러오는데 걸린 시간 : {}초'.format(stop - start))
    
    Model GradientBoosting CV score : 0.5810
    RMSE : 15811.1309
    Model XGBoost CV score : 0.5947
    RMSE : 15868.0485
    Model LightGBM CV score : 0.6131
    RMSE : 14330.6681
    Model LASSO Regression CV score : 0.6842
    RMSE : 19852.5360
    Model Elastic Net Regression CV score : 0.6841
    RMSE : 19848.9725
    Model RandomForset CV score : 0.5618
    RMSE : 15087.6387
    불러오는데 걸린 시간 : 1061.5614063540002초
    
    In [62]:
    #여러개의 모델로 만들어진 predict 데이터들의 평균을 구한다.
    
    models = [{'model':xgboost, 'name':'XGBoost'},
              {'model':lightgbm, 'name':'LightGBM'},
             {'model':forest, 'name' : 'RandomForest'}]
    
    def AveragingBlending(models, x, y, sub_x):
        for m in models : 
            m['model'].fit(x.values, y)
        
        predictions = np.column_stack([m['model'].predict(sub_x.values) for m in models])
        return predictions
    

    xgboost, lightgbm, forest 총 3개의 모델을 stacking하여 활용

    In [63]:
    start = timeit.default_timer()
    
    y_test_pred = AveragingBlending(models, train, target, test)
    y_test_pred = (y_test_pred[:, 0]*0.05 + y_test_pred[:, 1]*0.1 + y_test_pred[:, 2]*0.85)
    predictions = y_test_pred
    
    stop = timeit.default_timer()
    print('불러오는데 걸린 시간 : {}초'.format(stop - start))
    
    불러오는데 걸린 시간 : 294.5215947790002초
    
    In [64]:
    sub = pd.read_csv('submission.csv')
    
    In [66]:
    sub['transaction_real_price'] = np.expm1(predictions)
    
    In [67]:
    sub.to_csv('submission.csv', index=False)
    

    댓글

Designed by Tistory.