[심화세션]_1주차
사전 학습 정리
교재
- 주교재: [파이썬 데이터 분석 실무 테크닉 100]
- 부교재: [통계101 x 데이터 분석]
주교재
[1장] 웹에서 주문 수를 분석하는 테크닉 10
1. 데이터를 읽어들이자
1
2
3
4
5
6
7
8
9
10
11
12
13
# pandas 임포트, 변수에 파일 저장, 데이터의 첫 5행 표시
import pandas as pd
customer_master = pd.read.csv('customer_master.csv')
customer_master.head()
item_master = pd.read.csv('item_master.csv')
item_master.head()
transaction_1 = pd.read.csv('transaction.csv')
transaction_1.head()
transaction_detail_1 = pd.read.csv('transaction_detail_1.csv')
transaction_detail_1.head()
2. 데이터 결합(union)
1
2
3
4
5
6
7
8
9
transaction_2 = pd.read_csv('transaction_2.csv')
transaction = pd.concat([transaction_1, transaction_2], ignore_index = True)
transaction.head()
# .head()로는 제대로 결합됐는지 알 수 없음
print(len(transaction_1))
print(len(transaction_1))
print(len(transaction_1))
# 5000 1786 6786 -> 제대로 유니언된 것을 확인할 수 있다.
3. 매출 데이터끼리 결합(join)
transaction_detail 기준, transaction의 payment_date, customer_id 칼럼 추가
공통 데이터 칼럼: transaction_id
1
2
join_data = pd.merge(transaction_detail, transaction[["transaction_id", "payment_date", "customer_id"], on "transaction_id", how = "left"])
join_data.head()
1
2
3
4
print(len(transaction_detail))
print(len(transaction))
print(len(join_data))
# 7144 6786 7144
4. 마스터데이터 결합(조인)
1
2
3
join_data = pd.merge(join_data, customer_master, on = "customer_id", how = "left")
join_data = pd.merge(join_data, item_master, on = "item_id", how = "left")
join_data.head()
5. 필요한 데이터 칼럼 만들기
매출 = quantity * item_price
1
2
join_data["price"] = join_data["quantity"] * join_data["item_price"]
join_data[["quantity", "item_price", "price"]].head()
6. 데이터 검산
1
2
3
4
5
6
print(join_data["price"].sum())
print(transaction["price"].sum())
# 971135000 971135000
join_data["price"].sum() == transaction["price"].sum()
# True
틀린 데이터로 분석하지 않도록 데이터 가공 후 검산은 항상 신경 써야 한다.
7. 통계량 파악
- isnull(): 결손치가 True/False로 반환
- .isnull().sum(): 결손치 True 개수 합계
1
2
3
print(join_data["payment_date"].min())
print(join_data["payment_date"].max())
# 2019-02-01 2019-07-31
8. 월별 데이터 집계
과거 몇 년 간의 데이터에서 특정 범위 데이터만 추출해 월별로 매출 증감 파악
- payment_date 데이터형 확인
payment_date가 object형임을 확인
1
2
3
join_data["payment_date"] = pd.to_datetime(join_data["payment_date"])
join_data["payment_month"] = join_data["payment_date"].dt.strftime("%Y%m")
join_data[["payment_date", "payment_month"].head()]
- datetime의 dt를 사용해 년, 월 추출 & strftime 사용해 연월 작성
1
join_data.groupby("payment_month").sum()["price"]
- groupby: 집계 칼럼(payment_month)과 집계 방법(sum) 기술, price만 표시하기 위해 칼럼 지정
9. 월별, 상품별 데이터 집계
groupby를 이용해 월별, 상품별 매출의 합계, 수량을 표시해보자.
groupby에서 출력하고 싶은 칼럼이 여러 개 -> 리스트형으로 지정
pivot_table을 사용해 다시 집계
- pivot_table: 행, 칼럼 지정 가능. 행에는 상품명, 칼럼에는 월이 오게 index & columns 지정. values에는 집계하고 싶은 칼럼(price, quantity), aggfunc에는 집계 방법(sum)을 지정
10. 상품별 매출 추이 가시화
가시화 과정:
- 데이터 집계
- 집계된 데이터를 이용해 그래프 그리기
[2장] 대리점 데이터를 가공하는 테크닉 10
손으로 데이터를 입력하다 보면 입력 실수나 데이터 누락 등 ‘오류’가 많이 포함되기 마련이다.
11. 데이터 읽어 들이기
1
2
3
4
5
6
import pandas as pd
uriage_data = pd.read_csv("uriage.csv")
uriage_data.head()
kokyaku_data = pd.read_excel("kokyaku_daicho.xlsx")
kokyaku_data.head()
- 데이터의 정합성: 입력 오류나 표기 방법의 차이가 부정합을 일으키는 경우를 말한다.
12. 데이터의 오류 살펴보기
공백이 포함되거나 알파벳 대문자와 소문자가 섞여있는 경우, 시스템은 이를 다른 상품으로 집계하여 정확한 집계를 할 수 없다.
13. 데이터에 오류가 있는 상태로 집계하기
1
2
3
4
uriage_data["purchase_date"] = pd.to_datetime(uriage_data["purchase_date"])
uriage_data["purchase_month"] = uriage_data["purchase_date"].dt.strftime("%Y%m")
res = uriage_data.pivot_table(index="purchase_month", columns="item_name", aggfunc="size", fill_value=0)
res
데이터에 오류가 있는 상태로 집계 및 분석을 하면 전혀 의미 없는 결과가 나온다.
14. 상품명 오류 수정
1
2
print(len(pd.unique(uriage_data["item_name"])))
# 99
26개 상품이 99개로 늘어나 있는 것을 확인할 수 있다.
1
2
3
4
uriage_data["item_name"] = uriage_data["item_name"].str.upper()
uriage_data["item_name"] = uriage_data["item_name"].str.replace(" ", "")
uriage_data["item_name"] = uriage_data["item_name"].str.replace(" ", "")
uriage_data.sort_values(by=["item_name"], ascending=True)
1
2
3
4
5
print(pd.unique(uriage_data["item_name"]))
print(len(pd.unique(uriage_data["item_name"])))
# ['상품A' '상품S' '상품Z' ``` '상품T' '상품J']
# 26
15. 금액 결측치 수정
1
uriage_data.isnull().any(axis=0)
item_price만 결측치가 있는 것을 확인 가능
1
2
3
4
5
flg_is_null = uriage_data["item_price"].isnull()
for trg in list(uriage_data.loc[flg_is_null, "item_name"].unique()):
price = uriage_data.loc[(~flg_is_null) & (uriage_data["item_name"] == trg), "item_price"].max()
uriage_data["item_price"].loc[(flg_is_null) & (uriage_data["item_name"]==trg)] = price
uriage_data.head()
먼저, item_price 중 결측치가 있는 곳을 조사한다. 그리고 fig_is_null 변수에 어떤 행에 결측치가 있는지 저장한다.
list(): 변수의 값을 리스트 형식으로 변환
loc 함수: 조건에 일치하는 데이터 추출
uriage_data.loc[(~flg_is_null) & (uriage_data[“item_name”] == trg), “item_price”].max(): 결측치가 있는 상품의 제대로 된 금액 데이터 행을 loc로 찾고 가져온다.
~: 부정 연산자, ~flg_is_null은 flg_is_null == False 와 같은 의미
데이터가 제대로 수정되었는지 확인
1
uriage_data.isnull().any(axis=0)
1
2
3
for trg in list(uriage_data["item_name"].sort_values().unique()):
print(trg + "의최고가:" + str(uriage_data.loc[uriage_data["item_name"]==trg]["item_price"].max())
+ "의최저가:" + str(uriage_data.loc[uriage_data["item_name"]==trg]["item_price"].min(skipna=False)))
16. 고객 이름 오류 수정
1
2
3
kokyaku_data["고객이름"] = kokyaku_data["고객이름"].str.replace(" ", "")
kokyaku_data["고객이름"] = kokyaku_data["고객이름"].str.replace(" ", "")
kokyaku_data["고객이름"].head()
이름 입력 오류는 잘못 입력한건지 다른 사람인지를 판단할 수 없기에 단순히 프로그램으로 수정할 수 없다. 같은 이름의 데이터가 존재한다면 등록일, 생년월일 등 다른 정보를 이용해서 구분해야 한다.
17. 날짜 오류 수정
1
2
3
flg_is_serial = kokyaku_data["등록일"].astype("str").str.isdigit()
flg_is_serial.sum()
# 22
등록일의 데이터타입이 날짜가 아니라 숫자인 데이터가 22개임을 확인할 수 있다.
1
2
3
# 숫자를 날짜로 변경
fromSerial = pd.to_timedelta(kokyaku_data.loc[flg_is_serial, "등록일"].astype("float"), unit="D") + pd.to_datetime("1900/01/01")
fromSerial
- pd.timedelta() 함수를 이용해 숫자를 날짜로 변환. loc()를 이용해 flg_is_serial 조건으로 데이터 추출하고 날짜 변경.
엑셀에서 날짜가 2일 어긋나게 변환됨을 기억할 것.(날짜 데이터 출발 숫자와 2/29의 차이)
1
2
fromString = pd.to_datetime(kokyaku_data.loc[~flg_is_serial, "등록일"])
fromString
슬래시로 구분된 서식을 하이픈으로 구분된 서식으로 통일. 숫자를 날짜로 수정한 데이터와 서식을 변경한 데이터를 결합해 데이터 갱신
1
2
kokyaku_data["등록일"] = pd.concat([fromSerial, fromString])
kokyaku_data
숫자를 날짜로 수정한 데이터 fromSerial과 서식을 변경한 데이터 fromString을 concat으로 결합, 원래 ‘등록일’에 대입해 갱신.
1
2
3
4
5
# 등록월 집계 결과
kokyaku_data["등록연월"] = kokyaku_data["등록일"].dt.strftime("%Y%m")
rslt = kokyaku_data.groupby("등록연월").count()["고객이름"]
print(rslt)
print(len(kokyaku_data))
수정한 날짜에서 ‘등록 연월’을 작성하고 groupby()로 집계
1
2
3
4
5
# 등록일 칼럼에 잔여 숫자 데이터 확인
flg_is_serial = kokyaku_data["등록일"].astype("str").str.isdigit()
flg_is_serial.sum()
# 0
18. 고객 이름을 키로 두 개의 데이터 결합(join)
데이터 분석을 위해 매출 이력과 고객 정보를 결합한 데이터를 작성하자.
1장에선 정합성이 있는 데이터였기에 ID와 같은 공통키로 결합이 가능했지만, 여기서는 두 개 데이터의 서로 다른 열을 지정해 결합한다.
1
2
3
join_data = pd.merge(uriage_data, kokyaku_data, left_on="customer_name", right_on="고객이름", how="left")
join_data = join_data.drop("customer_name", axis=1)
join_data
이렇게 데이터를 가공하여 분석에 적합한 형태가 되었다. 이런 데이터 가공을 ‘데이터 정제’라고도 한다.
19. 정제한 데이터를 덤프
덤프 = 출력
1
2
3
4
# 마지막 수정: 칼럼 배치 조정 -> join_data에서 임의로 지정
dump_data = join_data[["purchase_date", "purchase_month", "item_name", "item_price", "고객이름", "지역", "등록일"]]
dump_data
1
2
# dump_data를 to_csv()를 통해 파일로 출력
dump_data.to_csv("dump_data.csv", index=False)
20. 데이터 집계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 데이터 불러오기
import_data = pd.read_csv("dump_data.csv")
# purchase_month를 세로축으로 집계
# 상품별로 집계
byItem = import_data.pivot_table(index="purchase_month", columns="item_name", aggfunc="size", fill_value=0)
# 매출 금액 집계
byPrice = import_data.pivot_table(index="purchase_month", columns="item_name", values="item_price", aggfunc="sum", fill_value=0)
# 고객 이름 별 구입 수 집계
byCustomer = import_data.pivot_table(index="purchase_month", columns="고객이름", aggfunc="size", fill_value=0)
# 지역 별 구입 수 집계
byRegion = import_data.pivot_table(index="purchase_month", columns="지역", aggfunc="size", fill_value=0)
byRegion
# 집계 기간에 구매 이력이 없는 사용자 확인
away_data = pd.merge(uriage_data, kokyaku_data, left_on="customer_name", right_on="고객이름", how="right")
away_data[away_data["purchase_date"].isnull()][["고객이름", "등록일"]]
# 집계 기간 내에 구매하지 않은 고객은 purchase_date가 null로 처리
# -> null 값 조사로 구매 이력 없는 사용자 확인 가능
부교재
[1장] 통계학이란? :데이터 분석에서 통계학의 역할
1.1 데이터를 분석하다
데이터는 수치의 모음으로, 막연히 바라보기만 해서는 무엇인지 제대로 알 수 없다.
데이터 분석의 목적
- 데이터 요약: ex) 평균
- 대상 설명: 대상이 가진 성질과 관계성을 밝히고, 이해한다
- 미지의 데이터 예측
cf.
- 실험군: 처리를 한 집단(신약 투여집단)
대조군: 비교를 위한 집단(위약 투여집단)
- 단일맹검법: 피험자에게 어느 약인지 알리지 않고 실험
- 이중맹검법: 연구자가 무의식적으로 실험에 영향을 줄 가능성을 배제하기 위해 연구자도 어느 약인지 모른 채 실험
1.2 통계학의 역할
통계학은 데이터 퍼짐 정도가 클수록 힘을 발휘한다
통계학은 데이터 퍼짐(산포)이나 불확실성에 대처하는 방법으로 확률론을 제공한다.
1.3 통계학의 전체 모습
- 기술통계(descriptive statistics): 수집한 데이터를 정리하고 요약하는 방법
추론통계(inferential statistics): 수집한 데이터로부터 데이터의 발생원 추정하는 방법
확률 모형: 대상의 성질 자체는 관찰도, 다루기도 어렵다. 이에 데이터가 비교적 단순한 확률 장치에서 생성되었다 가정하는 것을 확률 모형이라 부른다.
- 통계적 추론(statistical inference): 데이터에서 가정한 확률 모형의 성질 추정
- 가설 검정(statistical test): 세운 가설과 얻은 데이터가 얼마나 들어맞는지 평가, 가설 채택 여부 판단 방법
[2장]
2.1 데이터 분석의 목적과 알고자 하는 대상
- 구체적인 데이터 분석 목적을 정하는 것이 중요한 첫 단계다.
- 다음으로는 알고자 하는 대상을 명확히 하는 것이 중요하다.
2.2 모집단
‘지금 알고자 하는 대상은 무엇인지’ 그리고 ‘무엇을 모집단으로 설정할 것인지’의 문제에는 항상 주의를 기울여야 한다.
모집단 크기: 모집단에 포함된 요소(element)의 수
- 유한모집단: 모집단 중 한정된 요소만 포함 (ex. 1반 vs 2반)
- 무한모집단: 모집단 중 포함된 요고의 개수가 무한 (ex. 주사위, 신약 개발)
2.3 모집단의 성질을 알다
모집단의 성질을 알 수 있다면 대상을 설명하거나 이해할 수 있고, 미지의 데이터를 예측할 수도 있다.
모집단의 성질을 구하기 위한 방법:
- 전수조사: 분석할 데이터 = 모집단. 데이터 그 자체의 특징을 기술하고 요약하는 기술통계(descriptive statistics). 현실적인 제약으로 실현 불가능한 경우가 대부분.
표본 조사: 모집단의 일부를 분석하여 모집단 전체 성질 추정하는 추론 통계(inferential statistics). 표본/표본추출/표본조사 (ex. 선거 출구조사, 시청률)
- 표본 크기 = 표본의 개수 = 샘플 수
표본 크기는 모집단의 성질을 추정할 때 확실성이나 가설검정의 결과에도 영향을 끼치기에 통계분석에서 중요하다!
[3장]
3.1 데이터 유형
- 변수: 데이터 중, 공통의 측정 방법으로 얻은 같은 성질의 값
통계학에서 변수의 개수는 ‘차원’이라 표현되기도 한다. 고차원 데이터를 해석하는 경우 데이터 분석 난도가 높아진다.
다양한 데이터 유형
- 양적(수치형) 변수: 숫자로 나타낼 수 있는 변수
- 이산형
- 연속형
- 질적(범주형) 변수: 숫자가 아닌 범주로 나타낼 수 있는 변수
3.2 데이터 분포
히스토그램(도수분포도)은 데이터 분포를 그림으로 나타낸다.
히스토그램을 통한 시각화와 수치적인 분석 결과 모두를 이용하여 상호보완적으로 데이터를 바라보는 것이 중요하다.
3.3 통계량
통계량: 수집한 데이터로 계산을 수행하여 얻은 값
기술통계량(요약통계량): 데이터 그 자체의 성질을 기술하고 요약하는 통계량. 주로 양적 변수를 대상으로 계산.
다양한 기술통계량
대푯값은 매우 편리하지만 분포가 봉우리 형태가 아닌 경우와 같이 대푯값이 실제 데이터를 대변하지 못하는 경우도 있음을 주의하자.
- 분산과 표준편차: 데이터가 어느 정도 퍼져 있는지(산포도)를 파악하기에 좋다.
표본 분산의 성질: 1. 표본 분산은 0보다 크거나 같다.(모든 값이 같다면 0) 2. 산포도가 크면 표본 분산도 커진다.
- 이상값: 명확한 정의는 없으나, 평균값에서 표준편차의 2배 또는 3배 이상 벗어난 숫자
데이터 분석 현장에서는 시각화를 통해 이상값의 유무를 확인하고, 실제 값인지 혹은 실수로 생긴 값인지를 판단하는 것이 중요하다.
3.4 확률
- 확률변수: 일반적으로 표현하는 X와 같이 확률이 달라지는 변수
실현값: 확률변수가 실제로 취하는 값
확률분포
- 기댓값: E(X), 평균과 동일
- 분산과 표준편차
기댓값과 분산 이외에도 확률분포를 특징 짓는 값으로 왜도와 첨도가 있다.
- 왜도: 분포가 좌우대칭에서 어느 정도 벗어났는지
- 첨도: 분포가 얼마나 뾰족한지, 그래프의 꼬리가 차지하는 비율이 얼마인지
확률변수가 2개일 때
- 확률 변수 2개를 동시에 생각할 때의 확률 분포를 동시확률분포 P(X,Y)라 한다.
독립 X와 Y가 독립이면, P(X,Y) = P(X) x P(Y)
조건부확률
3.5 이론적인 확률분포
이론적인 확률분포는 수식으로 표현되며, 분포의 형태를 정하는 숫자인 파라미터(모수)를 가진다.
- 표준화