[오늘의 문제] 데이터 분석

shlim55·2025년 11월 21일

코딩테스트

목록 보기
179/223

미션: 서울 아파트 가격 데이터 분석

각 코드 셀의 지시사항대로 2022년 서울 아파트 거래 데이터를 분석해보도록 하겠습니다.

import pandas as pd
import numpy as np

1. 데이터셋을 불러오고 데이터 일부를 확인합니다.

import pandas as pd

df = pd.read_csv('seoul_apart_2022.csv')
df

2. 전체 데이터의 갯수와 자료형 등을 확인합니다.

print(type(df))
df.shape

df.info() 로도 가능하다.

3. 데이터프레임 df에서 사용하지 않을 특정 컬럼을 제거하세요.

  • drop을 활용해서 데이터 분석 과정에서 활용하기 어려운 컬럼들을 삭제합니다.
  • 삭제할 컬럼은 다음과 같습니다: "해제사유발생일", "중개사소재지", "번지", "본번", "부번", "도로명", "거래유형"
  • 컬럼 삭제가 원본 데이터프레임 df에 적용이 되어야 합니다.
df = df.drop(["해제사유발생일", "중개사소재지", "번지", "본번", "부번", "도로명", "거래유형"], axis=1)
df

4. "전용면적(㎡)" 컬럼의 제곱미터가 특수문자라 사용하기 어려움으로 일단 "전용면적"으로 이름을 바꾸세요!

  • 컬럼의 이름을 변경 후, 원본 데이터프레임에 반영하세요.
df = df.rename(columns = {'전용면적(㎡)' : '전용면적'})
df

5. "시군구"컬럼의 주소는 활용하기 쉽게 "구" 컬럼과 "동" 컬럼으로 분리합니다.

  • "시군구" 컬럼과 apply() 함수를 활용하세요.
  • 분리하는 로직은 문자열의 split() 함수를 활용하세요.
# 시군구 분리하기

df["구"] = df["시군구"].apply(lambda x: x.split(" ")[1])
df["동"] = df["시군구"].apply(lambda x: x.split(" ")[2])

df

df['구'] = df['시군구'].apply(lambda e: e.split()[1])
이렇게 해도 사실 서울특별시 강남구 개포동 이렇게 인덱스별로 저장 가능

6. 면적에 따라 아파트의 유형을 분류하려고 합니다.

  • category(e) 함수를 정의하고, 분류하는 코드를 작성하세요.
    • "전용면적"이 60 이하면 소형, 60보다 크고 85 이하면 중형, 85보다 크고 102 이하면 중대형, 102보다 크면 대형으로 분류됩니다.
  • apply() 함수와 위에 정의한 category() 함수를 활용하여, 분류된 값을 "유형" 컬럼으로 새로 추가하세요.
# 면적에 따라 아파트 유형을 분류하는 함수
def category(e):
    # "전용면적"이 60 이하면 **소형**, 60보다 크고 85 이하면 **중형**, 85보다 크고 102 이하면 **중대형**, 102보다 크면 **대형**으로 분류
    if e <= 60:
        return "소형"
    elif e > 60 and e <= 85:
        return "중형"
    elif e > 85 and e <= 102:
        return "중대형"
    else:
        return "대형"

df["유형"] = df["전용면적"].apply(category)
df

7. "계약년월" 컬럼과 "계약일" 컬럼을 "계약일" 컬럼에 합치고, 날짜타입으로 변경합니다.

  • "계약년월" 컬럼과 "계약일" 컬럼을 "문자열" 타입으로 변경 후, "계약일" 컬럼에 합치세요.
  • 합친 후, "계약일" 컬럼을 날짜 타입으로 변경하세요.
  • 날짜타입으로 변경할 때, format='%Y%m%d' 옵션을 추가하여 "계약일" 컬럼의 날짜 형식을 잘 인식하도록 합니다.
df["계약일"] = df["계약년월"].astype(str) + "" + df["계약일"].astype(str)
df["계약일"] = pd.to_datetime(df["계약일"], format='%Y%m%d')
df

사실 astype로 형변화만 해주면 됨 +""+는 없어도 된다..

8. "계약일" 컬럼의 데이터가 datetime으로 변경되었습니다. 이제 계약일 데이터를 활용해 "계약월"과 "계약요일" 컬럼을 생성해보겠습니다.

  • dt 속성을 활용하여, "계약월", "계약요일" 컬럼을 생성하세요.
  • "계약요일" 컬럼의 경우, 각각 '월', '화', '수', '목', '금', '토', '일' 형태로 변환하세요.
df['계약월'] = df['계약일'].dt.month
df['계약요일'] = df['계약일'].dt.dayofweek

week_map = {0:"월", 1:"화", 2:"수", 3:"목", 4:"금", 5:"토", 6:"일"}
df['계약요일'] = df['계약요일'].map(week_map)
df

좀더 간결한 코드문

df['계약월'] = df['계약일'].dt.month
df['계약요일'] = df['계약일'].dt.dayofweek
df['계약요일'] = df['계약요일'].map({0: '월', 1: '화', 2: '수', 3: '목', 4: '금', 5: '토', 6: '일'})
df

부동산 거래 데이터에서 가장 중요한 데이터는 "거래금액(만원)"입니다. 이 거래금액을 활용하여 정렬을 하거나 다양한 통계값을 계산할 수 있습니다.

9. "거래금액(만원)" 컬럼을 활용하기 전에 데이터의 결측치를 확인해보도록 하겠습니다.

df.isna().sum()

"거래금액(만원)" 컬럼에 33개의 결측치가 있습니다. 거래금액은 데이터 분석에서 굉장히 중요한 정보이기 때문에 거래금액 정보가 없는 데이터는 사용할 수 없고, 다른 통계값으로 채워넣기에도 좋지 않습니다.

마침 데이터가 12000개가 넘어서 꽤 많기 때문에, 이번에는 "거래금액(만원)"컬럼에 결측치가 있는 데이터는 아예 삭제해버리도록 하겠습니다.

10. 데이터프레임 df에서 "거래금액(만원)"컬럼에 결측치가 존재하는 데이터를 삭제하세요.

  • dropna를 활용해서 "거래금액(만원)" 컬럼에 결측치가 존재하는 아파트 거래 데이터를 삭제하세요.
  • 데이터 삭제 후 dropnaignore_index를 올바르게 설정하여 인덱스를 초기화해주어야 합니다.
df = df.dropna(subset=["거래금액(만원)"], ignore_index=True)
df.isna().sum()

df.info()

데이터가 33개 줄어들기는 했지만, 결측치가 있는 데이터가 삭제되었습니다.

info를 통해 데이터의 정보를 다시 확인해보면 "거래금액(만원)"컬럼의 경우 데이터타입이 object인 것을 확인할 수 있습니다.

11. 원활한 데이터 분석을 위해 콤마(,)를 삭제하고, 숫자형태 데이터로 바꾸어주도록 하겠습니다.

  • str.replace()를 활용하여 "거래금액(만원)" 컬럼의 콤마(,)를 삭제하세요.
  • 그리고 수치형 컬럼 형태로 타입을 변경하세요.
df["거래금액(만원)"] = df["거래금액(만원)"].str.replace(',','').astype(int)
df

아래처럼 해도 큰 차이는 없다.

df['거래금액(만원)'] = df['거래금액(만원)'].str.replace(',', '')
df['거래금액(만원)'] = pd.to_numeric(df['거래금액(만원)'])

df.info()

"거래금액(만원)" 컬럼의 데이터 타입이 정수형으로 바뀐 것을 확인할 수 있습니다.

12. 이제 거래금액을 기준으로 내림차순으로 정렬해보도록 하겠습니다.

  • "거래금액(만원)" 컬럼을 내림차순으로 정렬 후, 상위 10개 데이터를 출력하세요.
  • 원본 데이터프레임에 반영하지 않습니다.
print(df.sort_values("거래금액(만원)", ascending=False).head(10))

13. 이번엔 "거래금액(만원)" 컬럼의 평균값과 중앙값을 계산해보겠습니다.

  • "거래금액(만원)" 컬럼의 평균과 중앙값을 구하고 출력하세요.
print(df["거래금액(만원)"].mean())
print(df["거래금액(만원)"].median())

아파트의 거래금액 자체도 중요하지만 크기에 따른 가격 또한 매우 중요한 지표입니다.

"전용면적"컬럼의 단위는 제곱미터로, 이는 국제 표준 규격이지만 우리에게는 평 단위가 조금 더 익숙합니다.

14. 1평은 대략 3.3㎡ 이므로, "전용면적"컬럼의 값을 3.3으로 나누어 덮어씌우고 컬럼의 이름을 "전용면적(평)"으로 변경합니다.

  • round(값, 자리수) 반올림 함수를 활용하여, "전용면적" 컬럼을 3.3으로 나눈 후, 소수점 둘째자리까지 반올림하여 덮어쓰기를 하세요.
  • "전용면적" 컬럼을 "전용면적(평)" 컬럼으로 이름을 변경하세요.
df["전용면적"] = (df["전용면적"] / 3.3).round(2)
df = df.rename(columns= {"전용면적" : "전용면적(평)"})

다음과 같이 해도 동일함

df['전용면적'] = round(df['전용면적'] / 3.3, 2)
df = df.rename(columns={'전용면적' : '전용면적(평)'})

df.head()

15. 데이터프레임 df에 "평당금액" 컬럼을 생성하세요.

  • 시리즈 연산을 활용한 데이터 변환을 통해 df에 "평당금액" 컬럼을 생성하세요.
  • 평당금액은 "거래금액(만원)"값을 "전용면적(평)"값으로 나눈 값입니다.
  • 그리고 평당금액을 소수점 둘째자리까지 반올림하세요.
df["평당금액"] = (df["거래금액(만원)"] / df["전용면적(평)"]).round(2)
df

다음과 같이 해도 됨

df['평당금액'] = round(df['거래금액(만원)'] / df['전용면적(평)'], 2)
df.head()

16. 이제 평당금액을 기준으로 다시 내림차순 정렬해보도록 하겠습니다.

  • "평당금액" 컬럼을 기준으로 내림차순 정렬 후, 상위 10개 행을 출력하세요.
  • 원본 데이터프레임에 반영하지 않습니다.
print(df.sort_values("평당금액", ascending=False).head())

head(10)으로 해도 동일한 결과

앞서 거래금액을 기준으로 정렬했던결과 많이 다른 결과를 얻을 수 있습니다. 이러한 결과를 부동산 도메인 지식과 함께 활용한다면 유용한 분석이 이루어질 수 있을 것입니다. 이렇게 새로운 지표로 이루어진 컬럼을 생성하는 것은 데이터 분석 과정에서 매우 중요합니다.

17. 이번엔 "구"컬럼을 기준으로 그룹을 묶어 서울의 각 구별 평당금액의 평균값을 확인해보도록 하겠습니다.

  • groupby()를 활용하여, "구" 컬럼을 기준으로 그룹을 만든 뒤, "평당금액"의 평균을 출력하세요.
print(df.groupby("구")["평당금액"].mean())

20. 서초구의 동 중 평당금액 평균이 2번째로 높은 동의 이름을 입력하세요.

*groupby와 "구", "동" 컬럼을 활용하여 서초구의 각 동별 평당금액 평균값을 구할 수 있습니다.

  • "구" 컬럼을 활용하여 "구" 중에서 "서초구"의 각 동별 평당금액의 평균값을 df_grouped 변수에 저장하세요.
  • 위 변수를 활용하여 "평당금액"의 평균값이 2번째로 높은 동의 "이름"을 추출하여 출력하세요.
    • 힌트: "평당금액"의 평균 결과를 Series가 아닌 DataFrame 형태로 만드세요.
df_grouped = df[df["구"] == "서초구"][["동","평당금액"]] # - "구" 컬럼을 활용하여 "구" 중에서 "서초구"의 각 동별 평당금액의 평균값을 df_grouped 변수에 저장하세요.
# - 위 변수를 활용하여 "평당금액"의 평균값이 2번째로 높은 동의 "이름"을 추출하여 출력하세요.
filtered_df = df_grouped.groupby("동")[["평당금액"]].mean()# 데이터 프레임화
# print(filtered_df)

filtered_df = filtered_df.sort_values("평당금액", ascending=False)
# print(filtered_df)
filtered_df = filtered_df.reset_index()
print(filtered_df.iloc[1]["동"])
# print(filtered_df.index[1]) # 주석처리하고 위 방식대로 해도 됨 

좀더 간결한 풀이

df_grouped = df[df['구'] == '서초구'].groupby('동')[['평당금액']].mean()
df_grouped.sort_values('평당금액', ascending=False).iloc[1].name
profile
A Normal Programmer

0개의 댓글