데이터시각화2022 중간고사 -- 풀이포함
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from plotnine import *
(1)
아래의 그림을 보고 올바르게 해석한 것을 고르라. (모두 맞출경우만 정답으로 인정)
- 소윤: (a)의 경우 $(x_i,y_i)$의 산점도가 직선형태이므로 표본상관계수의 값을 해석하는 것이 두 자료의 관계를 파악할때 도움을 준다.
- 다호: (b)의 경우 $(x_i,y_i)$의 산점도가 이차곡선이므로 표본상관계수의 해석으로 두 자료의 관계를 모두 파악할 수 없다.
- 하니: (c)의 경우 주황색으로 표시된 점을 제외한다면 표본상관계수로 자료를 해석하기에 바람직하다.
- 도한: (d)도 (c)와 마찬가지로 주황색으로 표시된 점을 제외한다면 표본상관계수로 자료를 해석하기에 바람직하다.
(풀이)
- 정답: 소윤, 다호, 하니가 맞게 서술함.
- 도한이 틀린이유: 주황색점을 제외할 경우 $x$의 변화량이 0이므로 분모가 0으로 수렴. 따라서 상관계수의 해석이 무의미하다.
(2)
아래의 그림을 보고 올바르게 해석한 것을 모두 고르라. (모두 맞출경우만 정답으로 인정)
- 그림에 대한 배경설명은 10월17일,19일의 "아이스크림을 많이 먹으면 걸리는 병"을 참고
- 소윤: 아이스크림과 소아마비는 상관계수는 양수이다.
- 다호: 상관계수가 양수라는 정보만으로는 소아마비와 아이스크림사이에 인과성이 있다고 주장하기 어렵다.
- 하니: 소아마비와 아이스크림 사이에 존재하는 은닉변수 온도를 통제한다면 소아마비와 아이스크림 사이의 상관계수는 0에 가깝다.
- 도한: 하니의 분석에 따르면 소아마비와 아이스크림 사이의 인과성은 없다고 보아야 한다. (단 소아마비와 아이스크림 사이의 은닉된 변수는 온도가 유일하다고 가정한다)
(풀이)
- 정답: 소윤, 다호, 하니, 도한 모두 맞게 서술함
(1)
~(3)
주어진 자료에 대하여 다음을 시각화 하라. (maplotlib 이용)
x=[1,2,3,4]
y=[1,2,3,2]
(1)
출제의도: 마커변경, 색깔변경
plt.plot(x,y,'x',color='C1');
- 채점기준: 색깔이 정확하게 일치하지 않을 경우 0점으로 처리
(2)
출제의도: title설정
plt.plot(x,y,)
plt.title('TITLE',size=15);
(3)
출제의도: linetype 변경, dot connected-plot
plt.plot(x,y,'or--');
(4)
~ (5)
주어진 자료에 대하여 다음을 시각화 하라.
x=[1,2,3,4]
y1=[1,2,4,3]
y2=[1.1,1.9,3,5]
(4)
출제의도: legend
plt.plot(x,y1,'o--',label='y1')
plt.plot(x,y2,'o--',label='y2')
plt.legend();
(5)
출제의도: linetype, linewidth 변경
fig,ax = plt.subplots(1,2)
ax[0].plot(x,y1,'--',lw=2)
ax[1].plot(x,y2,'--',lw=4);
- 채점기준: 선의두께가 예시와 조금 달라도 만점으로 인정 (두께의 변화만 있으면 정답으로 인정함)
주어진 자료가 아래와 같다고 하자.
np.random.seed(43052)
x1,y1 = np.random.multivariate_normal([-2,-2],[[1,-0.8],[-0.8,1]],size=500).T
x2,y2 = np.random.multivariate_normal([2,2],[[1,-0.7],[-0.7,1]],size=500).T
(1)
matplotlib와 seaborn을 이용하여 아래와 같이 시각화 하라.
- alpha=0.1을 사용
fig,ax = plt.subplots(2,2)
ax[0,0].plot(x1,y1,'.')
ax[0,0].plot(x2,y2,'.',alpha=0.1)
ax[0,0].set_title("(a) matplotlib - highlight (x1,y1)")
sns.scatterplot(x=x1,y=y1,ax=ax[0,1])
sns.scatterplot(x=x2,y=y2,ax=ax[0,1],alpha=0.1)
ax[0,1].set_title("(b) seaborn - highlight (x1,y1)")
ax[1,0].plot(x1,y1,'.',alpha=0.1)
ax[1,0].plot(x2,y2,'.')
sns.scatterplot(x=x1,y=y1,ax=ax[1,1],alpha=0.1)
ax[1,0].set_title("(c) matplotlib - highlight (x2,y2)")
sns.scatterplot(x=x2,y=y2,ax=ax[1,1])
ax[1,1].set_title("(d) seaborn - highlight (x2,y2)")
plt.tight_layout()
- 채점기준: (b)와 (d)의 그림을 seaborn으로 생성하지 않을 경우 정답으로 인정안함
(2)
plotnine을 이용하여 아래와 같이 시각화하라.
- alpha=0.1을 사용
x=np.concatenate([x1,x2])
y=np.concatenate([y1,y2])
df = pd.DataFrame({'x':x,'y':y,'cat':['A']*len(x1)+['B']*len(x2)})
ggplot(df)+geom_point(aes(x='x',y='y',color='cat'),alpha=0.1)\
+geom_smooth(aes(x='x',y='y',color='cat'))\
+geom_smooth(aes(x='x',y='y'))
- 채점기준: 산점도, 그룹별추세선, 전체추세선이 모두 있을 경우만 정답으로 인정
아래의 코드를 활용하여 FIFA22의 자료를 불러온뒤 물음에 답하라.
df = pd.read_csv('https://raw.githubusercontent.com/guebin/DV2021/master/_notebooks/2021-10-25-FIFA22_official_data.csv')
df
(1)
연령별로 선수들의 잠재력을 시각화하고 싶다. 여기에서 잠재력은 아래의 수식의 Potential2를 의미한다.
Potential2 = Potential - Overall
아래의 세부지침에 맞추어 연령별 Potential2의 산점도와 boxplot을 그려라. -- (10점)
(세부지침)
step1: 결측치가 가장 많은 2개의 컬럼을 찾고 이를 제거하라.
step2: dropna()를 이용하여 결측치를 제거하라.
step3: Potential2 = Potential - Overall 를 이용하여 Potential2를 구하라.
step4: 구간 [0,20,22,26,100]를 설정하고 이를 기준으로 Age를 그룹화하라. (총 4개의 그룹으로 나누어져야 한다)
step5: 그룹화된 Age를 x축으로, Potential2를 y축으로, 색깔을 그룹화된 Age로 설정한 뒤 산점도와 박스플랏을 겹쳐그려라.
- 산점도의 파라메터: alpha=0.5,size=0.1,position='jitter'
- 박스플랏의 파라메터: alpha=0.8
(풀이)
df.info()
- 'Loaned From'와 'Marking'이 가장 결측치가 많이 포함되어있음
data1= df.drop(columns=['Loaned From', 'Marking']).dropna()\
.eval('Potential2 = Potential- Overall')\
.assign(Age = lambda df: pd.cut(df['Age'],[0,20,22,26,100]))
data1
fig = ggplot(data=data1)
scatter = geom_point(aes(x='Age',y='Potential2',colour='Age'),alpha=0.5,size=0.1,position='jitter')
boxplot = geom_boxplot(aes(x='Age',y='Potential2',colour='Age'),alpha=0.8)
fig+scatter+boxplot
- 채점기준: Age의 Label을 사용하지 않아도 만점으로 인정함.
(2)
포지션별로 선수들의 능력치와 Wage를 시각화하고 싶다. 아래의 dictionary를 이용하여 Position을 재정의하라.
position_dict = {
'GOALKEEPER':{'GK'},
'DEFENDER':{'CB','RCB','LCB','RB','LB','RWB','LWB'},
'MIDFIELDER':{'CM','RCM','LCM','CDM','RDM','LDM','CAM','RAM','LAM','RM','LM'},
'FORWARD':{'ST','CF','RF','LF','RW','LW','RS','LS'},
'SUB':{'SUB'},
'RES':{'RES'}
}
position_dict
아래의 세부지침에 맞추어 포지션별 ShotPower와 SlidingTackle의 산점도를 그려라. -- (30점)
세부지침
step1: 결측치가 가장 많은 2개의 컬럼을 찾고 이를 제거하라.
step2: dropna()를 이용하여 결측치를 제거하라.
step3: hint1과 position_dict을 참고하여 Position을 적절하게 변환하라. (변환된 값을 Position으로 저장할 것)
step4: hint2를 참고하여 Wage를 적절하게 변환하라. (변환된 값을 Wage에 저장할 것)
step5: Position=="DEFENDER" or Position=="FORWARD"에 해당하는 관측치를 고른 뒤 x축에 ShotPower, y축에 SlidingTackle 을 시각화하라. Position은 color로 구분하고 Wage는 size와 alpha로 구분하라.
hint1: Position column의 변환을 위한 코드
'<span class="pos pos18">CAM'.split('>')
hint2: Wage column의 변환을 위한 함수
def f(x):
if x[-1] == 'K' :
y= float(x[1:-1])*1000
elif x[-1] == 'M' :
y= float(x[1:-1])*1000000
else:
y= 0
return y
(풀이)
data2=df.drop(columns=['Loaned From', 'Marking']).dropna()\
.assign(Wage = lambda df: list(map(f,df['Wage'])))\
.assign(Position = lambda df: list(map(lambda x: x.split('>')[-1], df.Position)))\
.assign(Position = lambda df:
[key for x in df.Position for key in position_dict if x in position_dict[key]]
)
data2
fig = ggplot(data=data2.query('Position=="DEFENDER" or Position=="FORWARD"'))
scatter = geom_point(aes(x='ShotPower',y='SlidingTackle',color='Position',size='Wage',alpha='Wage'))
fig+scatter
- 채점기준: df['Position']이 아니라 df['Best Position']을 이용하여 자료를 변형하고 시각화 하는 경우 부분점수 없이 0점임
아래의 코드를 활용하여 Kaggle의 HRdataset을 불러오고 물음에 답하라.
df = pd.read_csv('https://raw.githubusercontent.com/guebin/DV2022/master/_notebooks/HRDataset_v14.csv')
df
(1)
데이터를 조사하고 올바르게 분석한 사람을 모두 고르라. (모두 맞칠경우만 정답으로 인정)
- 소윤: 근무인원수가 가장 많은 인종(RaceDesc)은 'White'이며 이는 'Asian'인종과 'Black or African American'의 합보다 많다.
- 다호: 'RaceDesc==White'의 성별(Sex)임금차이는 2000이상이다.
- 하니: 퇴직한사람(Termd==1)은 모두 104명이며 백인여성의 퇴직자수가 가장 많다.
- 도한: 퇴직한사람중 아시아인의 비율은 10%가 넘지 않는다.
(풀이)
모두 참이다.
데이터조사
df.info()
- EmpID가 missing이 없는 열임
소윤: 근무인원수가 가장 많은 인종(RaceDesc)은 'White'이며 이는 'Asian'인종과 'Black or African American'의 합보다 많다. --- 참
df.groupby(by='RaceDesc').agg({'EmpID':len})
29+80
다호: 'RaceDesc==White'의 성별(Sex)임금차이는 2000이상이다. --- 참
df.groupby(by=['RaceDesc','Sex']).agg({'Salary':np.mean})
68846.519231 - 65334.132530
하니: 퇴직한사람(Termd==1)은 모두 104명이며 백인여성의 퇴직자수가 가장 많다. --- 참
(df.Termd==1).sum()
df.groupby(by=['RaceDesc','Sex']).agg({'Termd':np.sum})
도한: 퇴직한사람중 아시아인의 비율은 10%가 넘지 않는다. --- 참
(df.Termd==1).sum()
df.groupby(by=['RaceDesc']).agg({'Termd':np.sum})
9/104
(2)
White, Black or African American, Asian 인종(RaceDesc)에 대하여 남여급여차이를 조사하고자 한다. 아래와 같은 Boxplot을 생성하라.
(풀이)
ggplot(data=df.query('RaceDesc == "White" or RaceDesc == "Black or African American" or RaceDesc == "Asian"'))\
+geom_boxplot(aes(x='RaceDesc',y='Salary',color='Sex'))