[부동산 | Phase2] 아파트 현황조사(고양시) - Python pandas 기본 (3부)



이제 두번째 질문으로 이어 나가 보자.


(2) 고양시 공동주택의 건물나이(건령)는 어느 정도 되었고, 어떤 분포를 가지고 있을까? 지은지 5년 이내 신규 아파트는 얼마나 될까?



지난 시간에 data frame을 다루는 방법 몇 가지를 익혔고, 건령을 구하는 방법도 이미 진행하였다. 

여러 개의 검색 조건 중 건령을 제일 먼저 계산 반영하였기에, 실질 질문 안에 들어 있는 건령에 대한 부분은 이미 계산이 끝났다.


z = apt_Goyang['사용검사일']

apt_Goyang['사용승인연도'] = z.str[0:4]
apt_Goyang['사용승인연도'] = apt_Goyang['사용승인연도'].astype(int)

apt_Goyang['건령'] = 2020 - apt_Goyang['사용승인연도']


그리고, 건령이 이미 계산되어 있기에 분포에 대한 답을 찾기에 앞서, 지은지 5년 이내 신규 아파트단지는 얼마나 많은지부터 먼저 알아보자.


필자가 작성한 코드는 다음과 같다. 


a1 = apt_Goyang.loc[apt_Goyang['건령'] <=5, :]
a1.to_excel('C:\\Users\\LG\\Desktop\\example\\a1_APTstat_Goyang.xlsx', sheet_name = "sheet1")


지난 시간에 설명드린 바와 같이, loc 함수를 사용해 '건령 5년 이내 아파트'를 검색하는 코드다.

엑셀로 export하면 아래 이미지와 같은 결과를 얻을 수 있다.



 단지명 기준 총 24개 단지가 5년 이내 건축된 것으로 확인된다. 


 필자는 24개를 엑셀의 요약을 통해 확인하였다. 그런데, 엑셀을 매번 열어보고 데이터의 개수를 세는 것은 번거로운 일이다. 게다가, 데이터가 매우 크다면? 아시다시피, 엑셀은 데이터가 커지면 커질수록 로딩에 시간이 많이 걸린다. 여간 귀찮고 시간 아까운 일이 아닐 수 없다. 



pandas data frame 또는 Series에서 행(데이터) 개수 세기


 이제 pandas에서 데이터의 개수를 세는 코드를 몇가지 살펴 보도록 하자.


 아시다시피, 엑셀에서는 가로줄을 '행', 세로줄을 '열'이라고 부르면서 자료를 취급한다. Pandas DataFrame도 같은 개념으로 접근한다면, '행'은 index, '열'은 'series'로 대비 된다. 그리고 series는 같은 속성을 가진 데이터의 1차원 리스트이다. 이 리스트들을 묶어내면 2차원의 data frame이 된다. 관계성을 가진 series끼리 묶어 data frame이 구성된다는 개념을 가늠해 놓도록 하자.


 데이터의 개수를 셀 때엔, data frame에서 셀 것인지, series에서 셀 것인지 선택할 수 있을 것이다. 

 익혀 두면 유익한 데이터 개수 세는 함수는 아래와 같다.


 1) 데이터프레임(df)에서 행 개수를 셀 때 : len(df)

 2) 데이터프레임(df)에서 NAN값이 아닌 데이터 행 개수 셀 때 : df.count( )

 3) Series(s)에서 행 개수를 셀 때 : len(s) 

 4) Series(s)에서 NAN값이 아닌 데이터 행 개수 셀 때 : s.count( )


 NAN은 Null값, 엑셀에서는 N/A로 표기되는 값을 의미한다. 결측치라고 불리며, pandas에서는 NAN으로 표기되기에 앞으로 이러한 값은 결측치 또는 NAN이라 표기하겠다. 결측치를 제외한 데이터 개수를 셀 때엔 count()함수를 사용한다는 점을 인지하자.

 그럼 우리 데이터에 적용해 보자. 아파트 단지가 몇개 인지 세면 충분하다.

 파이참을 통해 다음의 코드를 실행하면 24라는 값을 돌려준다. 정확하다.

print(a1['단지명'].count())

 이제 이 코드를 통해, 우리가 시각화를 진행하는 과정에서 PyQt5를 사용하여 GUI를 구성할 때, table을 만드는 것도 진행할 수 있을 것이다.



 이제 마지막 단계인 분포에 대해 알아보자.

 분포는 데이터를 분석하는 당사자가 무엇을 기준으로 한 분포냐에 따라, 다양하게 그 의미를 해석해 낼 수 있다. 필자가 아파트를 법원 경매 낙찰 받고자 하는 목적에서 입찰할만한 아파트를 targeting한다면 어느 기준을 가져갈 것인가 생각해 보았다.

 다음의 기준들이 경매 입찰자들이 어느 지역 아파트에 투자하는데 적합한지에 대한 고려 요소가 되지 않을까 싶다.


 1) 행정동상 어느 구역에 있나? 

 2) 단지에 공급된 세대수는 몇개나 되나?

 3) 지은지 몇년이 되었나?


 기준은 데이터를 활용하고자 하는 자가 여러 요소를 고려하여 추가될 수 있을 것이다.



pandas data frame에서 필요한 series만 추출하기


 필자는 어느 행정동에 가장 많은 아파트가 있는지 궁금하다. 통상, 아파트 단지가 많을수록 생활 기반 시설이나 체육시설, 상업시설이 잘 갖춰진 경우가 많다. 그리고 단지마다 공급된 세대수는 어느 정도인지도 궁금하다. 공급된 세대수가 많을수록, 관리비가 적게 나올 가능성이 크다. 그리고 지은지 얼마나 되었는지 궁금하다. 신축일수록 인기가 높을수밖에 없다. 하지만, 경매 전략상 이와 반대로 입찰하는 시나리오도 가능하다. 얼마든지 데이터를 활용하고자 하는 목적에 맞추어 기준을 세워 접근해 보자.


 일단, 필자의 시나리오에 맞추어 코딩을 해보자. 아래와 같다.


z = apt_Goyang['사용검사일']
apt_Goyang['사용승인연도'] = z.str[0:4]
apt_Goyang['사용승인연도'] = apt_Goyang['사용승인연도'].astype(int)
apt_Goyang['건령'] = 2020 - apt_Goyang['사용승인연도']
apt_Goyang['행정동'] = apt_Goyang['지번'].str[0:3]
# 필요한 series만 뽑아 쓰자.
a2 = apt_Goyang[['단지명', '행정동', '세대수','건령']]

 

행정동과 건령 계산에 관련한 코드는 이전 포스팅에서 다룬 내용 그대로이다.


raw data에서는 우리가 분석하는데 필요하지 않은 기타의 데이터가 모두 포함되어 있다. 쓸데 없는 series는 알고리즘을 수시로 돌릴 경우 resource만 잡아 먹는다. 모두 없애고 우리 궁금증을 해결해 줄 대상 series인 단지명, 행정동, 세대수, 건령만 추출하여 a2라는 새로운 DataFrame으로 추출하자.


a2를 엑셀로 export하여 보면 다음과 같은 결과를 확인할 수 있다.




그럼 1차로 정제된 DataFrame을 가지고, 우리는 우리의 궁금증을 해결해 나가야 한다.

필자의 코드를 이어서 보자.


a3 = a2[['행정동','단지명']].groupby(by="행정동", as_index=False).count()
a4 = a2[[
'행정동','세대수']].groupby(by="행정동", as_index=False).sum()
a5 = a2[[
'행정동','건령']].groupby(by="행정동", as_index=False).mean()

a6 = pd.merge(a3
,a4, on="행정동")
a7 = pd.merge(a6,a5, on="행정동")
a8 = a7.sort_values(by="세대수", ascending=False)


pandas data frame의 groupby, merge, sort_values 활용


 1) a3 = a2[['행정동','단지명']].groupby(by="행정동", as_index=False).count()

 

 pandas는 groupby() 함수를 통해 데이터의 요약값을 산출할 수 있다. 마치, 엑셀의 요약테이블 또는 피벗테이블을 만드는 것과 같다. count()함수는 그룹화의 기준이 되는 값("행정동")에 대해 산출희망series("단지명")에 대한 데이터의 개수를 세어준다.

즉, a3라는 dataframe은 행정동별 단지의 수를 돌려준다. 

 여기서, as_index = False라는 옵션은 groupby함수가 그룹라벨을 index로 쓰지 않도록 한다. 즉, 깔끔한 표형태를 구현하고자 넣어 준 것이다.



 2) a4 = a2[['행정동','세대수']].groupby(by="행정동", as_index=False).sum()


 groupby의 sum()함수는 산출희망series('세대수')의 총 합계를 내준다. 즉, a4라는 dataframe은 행정동별 세대수 합계를 돌려준다.



 3) a5 = a2[['행정동','건령']].groupby(by="행정동", as_index=False).mean()


 groupby의 mean()함수는 산출희망series('건령')의 평균값을 내준다. 즉, a5라는 dataframe은 행정동별 건령의 평균을 돌려준다. 



 4) a6 = pd.merge(a3,a4, on="행정동")


 merge함수는 on 값을 기준으로 같은 값을 가지는 각기 다른 2개의 DataFrame에 포함된 series들을 합쳐준다. 즉, '행정동'을 기준으로 a3에 포함되어 있는, '단지수'와 a4'에 포함된 '세대수합계'를 합쳐서 하나의 DataFrame으로 생성하여 준다.

그런데, 필자가 실행해 본 결과, 데이터프레임 합치기를 할 때엔 동시에 여러개를 할 수 없고, 각기 다른 데이터프레임 2개만에 한해서 실행이 되었다. 필자가 동시에 여러개를 하는 방법을 모르는 것일 수도 있으니, 방법이 있다면 독자분께 공유를 요청 드린다.



  5) a7 = pd.merge(a6,a5, on="행정동")


  이번 merge함수는 a3와 a4의 merge를 우선 끝내고 나온 DataFrame a6를 다시 a5와 합치기 위해서 사용되었다.



 6) a8 = a7.sort_values(by="세대수", ascending=False)


  sort_values() 함수는 by값을 기준으로 오름차순 또는 내림차순 정렬을 해준다. asceding = False는 내림차순 정렬을 해주고, True값을 주면 오름차순 정렬을 하게 된다. ascending값을 주지 않으면 default로 오름차순이 실행된다. 세대수를 기준으로 내림차순 정렬로 정리하였다.


이제 데이터 정리가 되었다. a8 DataFrame을 엑셀로 export하여 보면 아래와 같다.




정리된 데이터를 확보하였으니 시각화도 가능하고, 데이터가 알려주는 의미 찾기도 가능하다. 

해당 작업은 Phase3에서 논하도록 하자.




이번 포스팅에서는 '(2) 고양시 공동주택의 건물나이(건령)는 어느 정도 되었고, 어떤 분포를 가지고 있을까? 지은지 5년 이내 신규 아파트는 얼마나 될까?' 에 대한 데이터가공 작업을 진행하였다.


이번 질문을 통해서는 아래와 같은 항목들을 새롭게 배웠다.


a. pandas data frame 또는 Series에서 행(데이터) 개수 세기

b. pandas data frame에서 필요한 series만 추출하기

c. pandas data frame의 groupby함수에 대한 이해

d. pandas data frame groupby함수의 count(), sum(), mean() 활용하기 

e. pandas data frame의 merge 함수 사용하기

f. pandas data frame의 sort_values 함수 사용하기


 이제 마지막 3번 질문으로 추가적인 데이터분석을 위한 코드들을 습득해 보자.  



(4부에서 계속...)



반응형

+ Recent posts