본문 바로가기
부트캠프(LIKELION AIS7)/수업

[AI스쿨 7기, 4주차] 0303번 서울 코로나 / 0304 민간아파트분양 데이터 전처리 등

by aimaimee 2023. 4. 19.

0303번 - 전처리, 정규표현식, crosstab, boolean indexing으로 특정 조건 찾기, 피봇테이블, 그룹바이 / 타이타닉 과제 풀이 / 0304번- object 타입 바꾸기, 컬럼 삭제

멋쟁이 사자처럼 AI스쿨 7기, 박조은 강사님 강의

221011

1. 0303번 실습 파일

1.1 거주지

  • df["거주지"].value_counts() 출력 했을 때, 양천구, 용산구, 동작구 등이 위에도 있는데 밑에도 있다. 눈에 보이지 않는 공백 등이 있어서 str.strip()으로 전처리
    과제로 했을 때, 빈 막대 그래프가 나왔는데, 전처리 한 게 잘 반영이 안되서 그랬구나
  • 원래 value_counts()는 한 개 변수에 대해서만 비교를 할 수 있었는데, 작년부터 데이터프레임에서도 쓸 수 있도록 변경
  • 전처리 하고 결과가 잘 되었는지 확인하려면, "타시도"인 것만 찾아서 남아있는게 있는지 확인하는 것이 좋다.
  • = 하나는 할당, ==는 비교

1.2 전처리

  • 중복 되는 것이 없는지 확인 : print(df["거주구"].unique())
  • replace() : 데이터프레임, 시리즈에 사용
  • str.replace() : 시리즈(문자열)에만 쓸 수 있다.
  • Series accessor : str, dt, cat, sparse
  • 정규표현식 사용 여부 : regex=True

1.3 정규표현식 Regular expression

  • 문서 https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D
  • ex) 맞춤법이 틀린 것을 찾거나, 이메일 맞지 않는 형식 찾을 때, 당첨자 전화번호나 이름 일부만 공개, ㅋㅋㅋㅋ를 ㅋ로 변환
  • gr(a|e)y : |(pipe)는 or
  • 메타문자 정도는 알아두면 좋다. ex) glob해서 covid* 들어가는 문자 찾을 때
  • ^ 캐럿 : 처음 , [^ ]부정

1.4 그래프

  • 선 그래프 : 연속된 수치 데이터라고 가정하고 그리기 때문에, 중간에 x값들이 생략이 되어서 그려진다.
  • 범주형 데이터는 bar로 그리는게 좋다.

1.5 두 개 변수, crosstab

  • 연도, 퇴원현황
    • 컬럼에 띄어쓰기, 특수문자가 들어가면 : df.연도, df.요일과 같이 바로 쓰면 오류가 발생할 수 있으니 주의
    • normalize=True : 비율의 합이 1이 되게 계산. 백분위수로 보고 싶다면 *100 해서 본다.
    • pd.crosstab(index=df[""], columns=df[""])
    • 크로스탭은 0107번 실습도 참고
  • 연도, 월
    • ym.plot.bar() / ym.plot(kind="bar")
    • 월이 너무 많아서 색깔이 많으면 복잡하니까 축을 바꿔주는 것도 좋다.
    • 서울120 실습 때도 Transpose를 실습했다. T==transpose() 전치행렬
  • 연도, 요일
    • ym.columns = weekday_list
    • ym.columns = list("월화수목금토일")
    • weekday_list = [day for day in "월화수목금토일"] 리스트 컴프리헨션
    • ym.T.plot.bar()
  • 거주구, 연도월
    • 크로스탭은 피봇테이블을 사용하기 쉽게 감싸둔 것
    • style.background_gradient()
      • print(plt.colormaps()) : 쓸 수 있는 색상을 볼 수 있다.
      • gu_month.T.style.background_gradient(cmap="Greens") : cmap으로 색상 지정
    • style.bar() 막대로도 표시 가능
  • style
  • 두 개 이상 변수에 대해 비교, 그래프 그릴 때는 크로스탭으로

1.6 Boolean Indexing으로 특정 조건 찾기

  • df[조건식]은 컬럼을 바로 인덱싱하고, loc는 row와 column을 이용해 인덱싱하는 방식
    • df[df["거주구"] == "강남구"][["확진일", "접촉력"]]
    • df.loc[df["거주구"]=="강남구", ["확진일, "접촉력"]] : df.loc[조건, 열]로 간단하게 쓸 수 있다.
    • loc사용하면 속도가 아주 약간 빨라진다.
    • df[(df["거주구"]=="강남구") & (df["요일"]=="6")][["확진일", "접촉력", "요일명"]]
    • df[(df["거주구"]=="강남구") & (df["요일"]=="6")].loc[:, ["확진일", "접촉력", "요일명"]]
    • df.loc[(df["거주구"]=="강남구") & (df["요일"]=="6"), ["확진일", "접촉력", "요일명"]] : 가장 빠르다.
  • str.contains
    • df.loc[df["접촉력_대문자"].str.contains("PC"), "접촉력"].value_counts()
    • df[df["접촉력_대문자"].str.contains("PC방")]["접촉력"].value_counts()
  • isin
    • df.loc[df["거주구"].isin(["강남구", "서초구", "송파구"]), "접촉력"]

1.7 여행력

  • 해외, 국내로 구분해서 찾아볼 수도 있다.
  • ~는 조건을 반전시킨다. 연관기사 스크래핑 할 때도 사용했다.

1.8 치사율

  • pd.crosstab(df["연도"], df["퇴원현황"], normalize=True) *100 : 20년에 비해 치사율이 높아보인다. : 데이터량이 많으니까
  • normalize = 해당 항목의 수/ 전체 빈도수
  • y_count["치사율"] = (y_count["사망"] / (y_count["퇴원"] + y_count["사망"])) *100

1.9 피봇테이블

  • 피봇과의 차이는 : 연산 가능 여부
  • aggfunc = "len" / aggfunc="count" 빈도 세주는 것은 같다.
  • values로 설정해주면, 따로 []컬럼을 입력해주지 않아도 쉽게 설정할 수 있다.

1.10 그룹바이

  • 피봇테이블을 그룹바이를 하기 쉽게 감싼 기능
  • 처음에는 명시적으로 .groupby(by=[]) 해줘도 좋다.
  • 메서드, 함수에는 소괄호() / 인덱스에는 대괄호[]
  • Unstack
    • 기본값은 -1로 되어 있다. 그래서 level=-1은 생략해도 된다.
    • df.groupby(["연도", "월"])[["환자"]].count() : 환자를 [[]] 대괄호로 두 번 감싸면 시리즈가 아니라 데이터프레임 형태로 볼 수 있다.
  • 앤스콤, mpg, 서울 코로나에서 그룹바이 같은 것을 연습했는데, 여러번 연습하면 익숙해진다.

1.11 판다스 cheat sheet

https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf

  • Tidy Data : 아파트 분양가에서 실습해 볼 것이다.
  • 잡코리아팀 : 키 value 방식의 데이터프레임이 아니라 [[]]데이터프레임을 통해 수집해줌.
  • concat : 일별시세, 뉴스기사, 서울120 등 / 행으로 합칠 때 / 옆으로 합칠 때(일별 시세 비교) : axis = 1
  • sort_values : 첫 판다스 실습 때도 사용해봤다. 여러 개 지정도 가능하다. / ascending = 순차, 역순, 하나만, 여러개 정렬 할 것인지
  • rename 해서도 컬럼 이름을 바꿀 수 있다.
  • 확진일 빈도수 구하기 : sort_index()
  • reset_index() 겹치는 인덱스 있어서 초기화 하고 싶을 때 사용해보았다.
  • drop(columns=[]) 컬럼 지정해서 삭제
  • Subset Observations : drop_duplicates(), sample(frac)-frac은 처방 데이터 때 데이터가 많아서 사용해 볼 것
  • nlargest, nsmallest도 실습을 해 보았다.
  • Subset Variables
  • df[[""]]
  • df[""] = df.컬럼명
  • df.filter : 특정 컬럼, 변수만 가져올 때
  • Query 기능 : 사용을 권장하지 않는다. 내부에서 동작하는 원리는 비슷하기 때문에 굳이 두 가지 방식을 다 배울 필요가 없다.
  • Subsets 에서 iat와 at도 권장하지 않는다.
  • iloc, loc : fancy indexing
  • regex 정규표현식
    • . 점이 특별한 뜻을 가지기 때문에 예외 처리를 해달라.
      - ^Sepal : sepal로 시작하는 것을 찾아라
  • Summarize Data : value_counts, len, shape, nunique, describe
  • Group Data : groupby / agg / cumsum : cumulative sum : 서울코로나에서 해봤다. 확진수 구한 다음 누적 확진수 구할 때
  • merge , isin

2. 타이타닉 과제 풀이

  • 결측치가 embarked나 embark_town 둘 중 하나에서만 나왔으면 안 나온 곳에서 쓸 수 있을지 고민했을텐데, 동시에 결측치가 있다.
  • describe
    • min : 0살이 안된 아이가 있다.
    • count : 결측치가 꽤 있다.
  • sum(df["embark_lower"].str.contains("south")==True)
    • df["embark_lower"].str.contains("south").sum() / count()는 결측치를 포함해서 더하게 되서 값이 다르게 나온다.
  • child라는 새로운 컬럼에 담아 파생 변수를 만들어주었다.
  • df[df["fare"] > 500]["fare"] / df.loc[df["fare"]>500, "fare"]
  • df.loc[df["pclass"] == 3) & (df["embarked"] == "Q"), "fare"].mean() / df[(df["pclass"] == 3) & (df["embarked"] == "Q")]["fare"].mean()
  • fillna(0) 서울 코로나에서도 써보았다. / 현실에서는 데이터가 왜곡될 수 있기 때문에 0 으로 채우는 것을 권장하지 않는다.
  • df["deck"].value_counts().sort_index() / df.groupby("deck")["deck"].count().sort_index()
  • df[df["pclass"] == 1]["fare"].median() / df.loc[df["pclass"] == 1, "fare"].median()
  • df.sort_values(by="age", ascending=False) / df["age"].nlargest(5)

3. 07번 강의 파일

  • 왜 분석하기 좋은 데이터가 아닐까?
    • 종교와 income이라는 변수가 피봇테이블 형태로 되어 있다.
    • melt로 녹이게 된다. 열columns에 있던 데이터를 행row으로 녹인다.
  • Tidy data : 각 변수가 열이고, 관측치가 행이 되도록 배열된 데이터
  • long-form / wide-form : https://seaborn.pydata.org/tutorial.html 에서 많이 봤다.

4. 0304번 실습 파일

수도 코드

1) 2013~2015 연도와 월을 컬럼으로 만들어 줍니다.
최근 2015~ 데이터와 같은 형태로 만들어 줍니다.
2) 2015~ 제곱미터당 평균 분양가격 => 3.3 제곱미터당 가격으로 변경합니다.
전용면적을 전체만 사용합니다.
3) 1), 2) 데이터를 concat 으로 병합해서 하나로 만들어 2013~ 최근까지의 분양가를 분석합니다.

4.1 분양가격 object타입 바꾸기

  • info : 분양가격 : object 타입으로 되어 있다. 결측치가 꽤 있다.
  • isnull말고 isna로 결측치를 구할 수 있다.
  • pd.to_numeric(df_last["분양가격"]) : 비어 있는 문자열 때문에 에러가 난다.
  • error=raise기본값. 에러가 발생하면 에러가 보인다.
  • 결측치를 강제로 NaN값으로 바꿔라, 숫자로 진행, 문자가 포함되어 있으면 강제로 NaN값으로 변경 : error = coerce
  • ignore : invalid한 값을 그냥 출력
  • df_last["분양가격"].str.replace("[^0-9]", "", regex=True) : 숫자를 제외한 문자를 빈문자로 변경하는 정규 표현식

4.2 규모 구분

  • 전용 면적이 계속 포함되어서 나온다. 불필요하므로 str.replace해서 전처리
  • regex=True는 경고메시지 출력 여부

4.3 컬럼 삭제

  • df_last.drop(labels=["규모구분", "분양가격"]) : axis 기본값이 0이기 때문에 에러 메시지가 뜬다. axis가 0인지 1인지 명시해줘야 한다.
  • 이 과정을 줄이려면 그냥 columns로 해주면 된다.
  • 삭제한 것은 다시 df_last에 담아줘야지 결과가 반영이 된다.
  • 메모리 용량이 334에서 239로 조금 줄어들었다.

5. 퀴즈

12/12문제

5.1 맞았지만 애매한 것

  • 3번 문제 : Hadley Wickham이 정의한 tidy data의 정의는 무엇일까?
    • 관측치가 행이고 변수가 열이 되는 것
    • 관측치가 열이고 변수가 행이 되는 것
  • 6번 문제 : isnull.sum()으로 결측값의 갯수를 계산할 때 이렇게 나타낼 수 있는 이유는 ? __isnull()의 True==1이며, False==0으로 True값으로 연산이 가능하기 때문이다.

댓글