저번주 금요일에 pandas 개인과제가 나왔다. 1~3번 밖에 풀지 못했지만 팀원들의 과제 리뷰와 함께 해설 강의를 함께 리뷰 해보자.
타이타닉 데이터는 타이타닉호 생존자, 사망자에 관한 데이터입니다.
- 나의 풀이
조건1과 조건2에 해당하는 데이터로 필터링하고 해당 데이터를 조건3에서 주어진 4가지 컬럼으로만 추려서 10개 만 출력한다.
첫번쨰로 조건1을 (df['age']>=20) & (df['age']<40)으로 쓰고 조건2에서 pclass가 1등급 혹은 2등급인 승객을 찾기위해 .isin([1,2])을 사용해 (df['pclass'].isin([1,2]))으로 써준다음 다 합치면 상위 두가지 조건을 모두 필터링 한 데이터가 주어진다.
filtered_data = df[(df['age']>=20) & (df['age']<40) & (df['pclass'].isin([1,2]))]
두번쨰로 column을 survived, pclass, age, fare만 나오게 출력하면
filtered_data2 = filtered_data[['survived', 'pclass', 'age', 'fare']]
마지막으로 .head(10)으로 10개만 추출해주면 끝이다.

- 다른분 의 풀이
팀원들의 풀이에서 나와 다른점은 다들 필터링을 한 후 컬럼을 지정하여 출력하는 과정에서 .loc를 사용해서 지정해준후 .reset_index()로 인덱스를 새로 지정해 주었다.
아무래도 필터링된 데이터를 깔끔하게 정리 해줄 필요가 있어 보인다.

간단한 고객 데이터와 주문 데이터를 합치고, 주문여부에 따라 고객을 분류하고자 합니다.
- 나의 풀이
import pandas as pd
import numpy as np
#고객 테이블
customers = pd.DataFrame({
'고객번호': [1001, 1002, 1003, 1004, 1005, 1006, 1007],
'이름': ['승철', '동경', '예나', '혜연', '장훈', '채운', '다연']
})
#주문 테이블
orders = pd.DataFrame({
'cno': [1001, 1001, 1005, 1006, 1008, 1001],
'금액': [10000, 20000, 15000, 5000, 100000, 30000]
})
위에 문제에서 주어진 두 테이블을 고객테이블을 기준으로 합친다음 결측치를 0으로 채워주고 주문금액에 따라 '구매','비구매'로 분류하여 "구매여부"컬럼을 추가해준다.
첫번째로 두 테이블을 고객기분으로 합쳐야 하는데 SQL에서는 left join을 사용하였지만 python에선 merge를 사용하여 한쪽 테이블 기준으로 합칠 수 있다.
result1 = customers.merge(orders1, how='left', left_on='고객번호', right_on='cno')
위와 같이 써주면 sql에서 사용한 join처럼 on으로 공통 칼럼을 지정해주듯이 left_on='고객번호', right_on='cno'으로 이어 줄수 있다. 그러면 'cno'가 '고객번호'로 인식되어 겹쳐진다.
두번째로 결측치가 0으로 바뀌도록 .fillna(0)을 하면 결측치가 채워진다.
세번째는 구매여부를 분류하는 구매여부 칼럼을 만들어 주기위해 데이터 프레임에 함수처리를 하는 .apply()로 lambda를 사용하여 금액이 0이 아니면 '구매', 그 이외의 경우 '미구매'로 처리하고 분류된 항목을 '구매여부'컬럼으로 할당해주면 끝이다.
result1 = customers.merge(orders1, how='left', left_on='고객번호', right_on='cno')
result2 = result1.fillna(0)
result2['구매여부'] = result2['금액'].apply(lambda x: '구매' if x > 0 else '미구매')
result2 = result2[['고객번호', '이름', '금액', '구매여부']]
result2
이렇게 하면 완성이긴 한데 개인적으로 같은 구매자가 여러번 보이는게 싫어서 orders 테이블을 먼저groupby()로 묶어주었다.
orders1 = orders.groupby('cno', as_index=False)['금액'].sum()
result1 = customers.merge(orders1, how='left', left_on='고객번호', right_on='cno')
result2 = result1.fillna(0)
result2['구매여부'] = result2['금액'].apply(lambda x: '구매' if x > 0 else '미구매')
result2 = result2[['고객번호', '이름', '금액', '구매여부']]
result2

이렇게 하고 나서 보니 금액을int로 해줘서 정수처리 하는거랑 금액컬럼의 이름을 총금액으로 해줘야 되나 싶긴하다.
- 정답 풀이
# 방법1 orders.rename(columns = {'cno':'고객번호'}, inplace = True) df = pd.merge(customers, orders, on = "고객번호", how = "left")# 방법2 df = pd.merge(customers, orders, left_on = "고객번호", right_on = "cno", how = "left") df.drop(columns = "cno", inplace = True)df['금액'] = df['금액'].fillna(0).astype(int) df["구매여부"] = "구매" df.loc[df["금액"]==0, "구매여부"] = "미구매" #df["구매여부"] = np.where(df["금액"] > 0, "구매", "미구매") df
먼저 두가지 방법으로 merge를 하는데 orders테이블에서 cno를 customers테이블과 같게 고객번호로 이름을 바꿔준후 합치는 방법이 있고 다음은 내가 한 것처럼 left_on과 right_on을 써주는데 추가로 .drop()으로 cno칼럼을 날려준다.
다음은 팀원들과 미리 리뷰했을때 나온 지적중에 정수로 변환 안한것이 있었는데 역시나 풀이에도 금액의 결측치 처리를 할때 astype(int)로 정수처리 해주는걸 볼수 있다.
마지막으로 구매여부 칼럼을 추가할때 구매를 디폴트 값으로 먼저 칼럼을 만들어준다음 .loc()로 금액이 0인 경우에 미구매로 처리되도록 한다.
추가로 numpy를 사용하여 df["구매여부"] = np.where(df["금액"] > 0, "구매", "미구매")로 조건을 걸어서 할수도 있다.
- 나의 풀이
import pandas as pd
import numpy as np
import seaborn as sns
iris= sns.load_dataset("iris")
3-1) 불러온 데이터셋에서 species로 groupby()한 다음 agg(['mean', 'std'])으로 평균과 표준 편차를 구한다.
require1 = iris.groupby('species').agg(['mean', 'std'])
3-2) 4가지 변수의 상관관계를 분석하고 그중 가장 상관관계가 높은 변수 두개 를 찾는다.
이 문제는 구글링 하다가 풀이 과정이 어렵긴 한데 가장 쉽게 푸는거 같아서 열심히 배껴서 풀었다.
먼저 상관관계를 분석하기 위해서 .corr을 사용해야 하는데 그냥 하면 iris에 숫자열 이외의 정보도 있기 때문에 오류가 뜬다 그래서 numeric_iris = iris.select_dtypes(include=np.number)숫자열로 된 정보만 집은 데이터를 따로 만든다음 상관 계수를 구한다음
numeric_iris = iris.select_dtypes(include=np.number)
corr_iris = numeric_iris.corr()
corr_iris = corr_iris.apply(lambda x: round(x,2))
s = corr_iris.unstack()
df = pd.DataFrame(s[s < 1].sort_values(ascending=False), columns=['corr'])
max_corr = df.head(2)
print(f"가장 상관관계가 높은 두 변수: {max_corr}")
3-3) 3-2에서 구한 두 변수를 x,y축으로 두고 species에 따라 분류되도록 matplotlib을 import 하여 scatterplot을 그린다.