2021년 2학기 데이터시각화 특강 중간고사 풀이
- 예시 a-c, b-d
- Answer a-c, b-d
자료
x=[1,2,3,4]
y=[1,2,4,3]
시각화예시
x=[1,2,3,4]
y=[1,2,4,3]
fig,((ax1,ax2),(ax3,ax4))=plt.subplots(2,2)
ax1.plot(x,y,'--bo')
ax2.plot(x,y,'or')
ax3.plot(x,y,'xk')
ax4.plot(x,y,'--m.')
(하니) 그림 (a)-(d)는 모두 양의 상관계수를 가진다.
(나애리) 그림 (b)는 산점도가 직선이 아니라 곡선의 모양을 띄고 있으므로 상관계수는 0이다.
(홍두깨) 그림 (c)에서 상단의 이상치를 제외하면 상관계수는 1이다.
(고은애) 그림 (d)의 우측 이상치의 값을 적절하게 바꾸면 (d)의 상관계수를 음수로 만드는 것이 가능하다.
(이창수) 그림 (c)역시 상단의 이상치 값을 적절하게 바꾸면 (c)의 상관계수를 음수로 만드는 것이 가능하다.
- Anwer: 하니, 홍두꺠, 고은애, 이창수
(하니) 아이스크림과 소아마비는 양의 상관관계에 있다.
(나애리) 상관계수의 값이 1에 가까울수록 아이스크림과 소아마비의 인과성이 명확하다고 볼 수 있다.
(홍두깨) 비슷한 온도를 가진 관측치에서는 아이스크림과 소아마비의 상관계수가 0에 가깝다.
(고은애) 온도를 통제하였을 경우 아이스크림과 소아마비의 상관계수가 0이므로 둘 사이의 인과성이 있다고 보긴 어렵다. (단, 온도를 통제하였을 경우에는 아이스크림은 랜덤으로 먹었다고 가정한다.)
- Answer: 하니, 홍두깨, 고은애
아래의 코드를 활용하여 FIFA22의 자료를 불러온뒤 물음에 답하라.
df=pd.read_csv('https://raw.githubusercontent.com/guebin/2021DV/master/_notebooks/2021-10-25-FIFA22_official_data.csv')
import pandas as pd
df=pd.read_csv('https://raw.githubusercontent.com/guebin/2021DV/master/_notebooks/2021-10-25-FIFA22_official_data.csv')
df.loc[:,['Loaned From','Marking']]
- 내 Answer
df.drop(['Loaned From','Marking'],axis=1)
- 교수님 Answer
df.iloc[:,map(lambda x: 'Loaned From' != x and 'Marking' != x ,df.columns )]
- 내 Answer
len(df.drop(['Loaned From','Marking'],axis=1))-len(df.drop(['Loaned From','Marking'],axis=1).dropna())
- 교수님 Answer
df.iloc[:,map(lambda x: 'Loaned From' != x and 'Marking' != x ,df.columns )].dropna()
print(str(16710-14398),'개가 제거되었다.')
(d) (c)의 결과에 아래의 코드를 활용하여 Wage
의 값을 적절하게 변환하라.
### 코드1
def convert_currency(value):
floatvalue = 0.0
strvalue=""
if "M" in value:
strvalue=value.replace("M","").replace("€","")
floatvalue=float(float(strvalue)*1000000)
elif "K" in value:
strvalue=value.replace("K","").replace("€","")
floatvalue=float(float(strvalue)*1000)
else:
floatvalue=value.replace("€","")
return floatvalue
- 교수님 Answer
def convert_currency(value):
floatvalue = 0.0
strvalue=""
if "M" in value:
strvalue=value.replace("M","").replace("€","")
floatvalue=float(float(strvalue)*1000000)
elif "K" in value:
strvalue=value.replace("K","").replace("€","")
floatvalue=float(float(strvalue)*1000)
else:
floatvalue=value.replace("€","")
return floatvalue
df=df.iloc[:,map(lambda x: 'Loaned From' != x and 'Marking' != x ,df.columns )].dropna()
df['Wage']=list(map(convert_currency,df.Wage))
해당 함수의 경우 원하는 변수에 중복 적용시키면 에러뜬다!
- x축을
Best Position
으로 하고 y축은Value
의 평균으로 할 것 Value
가 가장 높은 3개의 포지션을 다른색으로 하이라이팅 할 것
시각화예시
- 교수님 Answer
df['Value']=list(map(convert_currency,df.Value))
import numpy as np
_df=df.groupby('Best Position').agg({'Value':np.mean})\
.rename(columns={'Value':'mean(Value)'})\
.sort_values('mean(Value)',ascending=False)\
.reset_index()
_df['Highlight']=_df['mean(Value)']>=_df['mean(Value)'][2]
_df
from plotnine import *
ggplot(_df)+geom_bar(aes(x='Best Position',y='mean(Value)',fill='Highlight'),stat='identity')
- 내 Answer
df3=df.groupby(by='Best Position').agg({'Value':np.mean}).rename(columns={'Value':'mean(Value)'}).reset_index()
def f(x):
if x=='CF':y='True'
elif x=='CM':y='True'
elif x=='LW':y='True'
else: y='False'
return y
df3['Bp']=df3['Best Position']
df3['Hightlight']=list(map(f,df3.Bp))
ggplot(df3)+geom_bar(aes(x='Best Position',y='mean(Value)',color='Hightlight',fill='Hightlight'),stat='identity')
세부사항
(i) Best Position
의 값을 바탕으로 면분할을 하라.
(ii) Age
를 색으로 표현하라.
(iii) 산점도의 투명도는 alpha=0.5
로 size=0.5
로 설정할 것.
ggplot(df)\
+geom_point(aes(x='Dribbling',y='SlidingTackle',color='Age'),alpha=0.5,size=0.5)\
+facet_wrap('Best Position')
(하니) 포지션 GK
에 있는 선수는 Dribbling
, SlidingTackle
값이 다른포지션대비 상대적으로 낮다.
(나애리) 모든 포지션에서 Dribbling
, SlidingTackle
은 서로 독립이라 볼 수 있다.
(홍두깨) 포지션 CAM
은 나이와 Dribbling
사이에 양의 상관관계에 있다.
(고은애) 포지션 CB
은 나이와 Dribbling
사이에 상관계수가 거의 0이다.
- Answer: 하니, 홍두깨, 고은애
세부사항
- x축: Dribbling, y축: SlidingTackle 로 설정
- Value에 따라 점의 크기를 다르게 설정
- 나이에 따라 색깔을 다르게 설정
시각화예시
- 교수님 Answer
ggplot(df.loc[(df['Best Position']=='CAM') |(df['Best Position']=='CB')])\
+geom_point(aes(x='Dribbling',y='SlidingTackle',color='Age',size='Value'),alpha=0.5)\
+facet_wrap('Best Position')
- 내 Answer
웬만하면 객체에 저장하지 말 것. 파이썬의 경우 데이터가 독립적으로 존재하지 않으려고 하는 경향이 있어서(그래서 빠르기도 함) 잘못하면 원본 데이터가 변할 가능성이 존재한다!
a=df.groupby(by='Best Position').get_group('CAM')
b=df.groupby(by='Best Position').get_group('CB')
c=pd.concat([a,b])
ggplot(c)+geom_point(aes(x='Dribbling',y='SlidingTackle',color='Age',size='Value'),alpha=0.3)+facet_wrap('Best Position')
(하니) AGE
와 Value
는 양의 상관관계에 있다.
(나애리) 따라서 축구선수는 AGE
가 증가함 따라 Value
가 올라가는 것을 알 수 있다. 즉 AGE
와 Value
사이에는 인과성이 있다.
(홍두깨) 포지션 CAM
은 Dribbiling
능력과 Value
가 양의 상관관계에 있어보인다.
(고은애) 반면에 포지션 CB
는 Dribbling
능력보다는 SlidingTackle
이 Value
와 양의 상관관계에 있다고 볼 수 있다.
- Answer: 하니, 홍두깨, 고은애
공원에서 뛰는것을 좋아하는 강아지 하니가 있다. 아래는 강아지 하니가 주인과 함께 공원을 산책한 경로이다. 산책코스는 아래와 같이 집에서 공원으로 가는 A코스와 공원에서 집으로 오는 B코스로 나누어진다.
-
A코스: 집 $\to$ 카페 $\to$ 초등학교 정문 $\to$ 공원
-
B코스: 공원 $\to$ 초등학교 후문 $\to$ 동물병원 $\to$ 집
각 위치의 좌표는 아래와 같다.
- 집: (0,0)
- 카페: (1,2)
- 초등학교 정문: (4,3)
- 공원: (5,5)
- 초등학교 후문: (4.1,3)
- 동물병원: (1,0.5)
집에서 출발시에 하니의 체력은 100이며, 각 중간지점에서 하니의 체력은 이동거리에 비례하여 감소한다고 하자. 예를들어 A코스-카페에서 하니의 체력은 아래와 같이 계산할 수 있다.
- $100- \sqrt{1^2+2^2}$
또한 하니는 공원정문에서 달리기를 시작하였고 이후에 60의 체력을 소진한뒤 공원후문에 도착하였다고 하자. (즉 공원정문에서하니의 체력이 $x$ 라면 공원후문에서 하니의 체력은 $x-60$ 이다.)
하니의 이동경로에 따른 체력의 변화를 시각화 하라.
(풀이)
- 내 Answer
x=[0,1,4,5,5,4.1,1,0]
y=[0,2,3,5,5,3,0.5,0]
def inc(x,y): return x**2+y**2
def f(x,y):
if x=='B':
y=y-70
elif x=='A':
y=y
return y
g=np.sqrt(np.array(list(map(inc,x,y))))
g1=100-np.array(g.cumsum())
course=['A']*4+['B']*4
df1=pd.DataFrame({'x':x,'y':y,'g1':g1,'course':course})
df1
def f(x,y):
if x=='B':
y=y-70+50**0.5
elif x=='A':
y=y
return y
df1['stamina']=list(map(f,df1.course,df1.g1))
df1
ggplot(df1)+geom_line(aes(x='x',y='y',size='stamina',color='course'))+geom_point(aes(x='x',y='y'))
- 교수님 Answer
x=[0, 1, 4, 5, 5, 4.1, 1, 0]
y=[0, 2, 3, 5, 5, 3, 0.5, 0]
course=['A']*4 + ['B']*4
_delta=[np.sqrt((x[i]-x[i-1])**2+(y[i]-y[i-1])**2)for i in range(len(x))]
stamina = np.array([100,100,100,100, 40, 40, 40, 40]) - [sum(_delta[:(i+1)]) for i in range(8)]
ggplot(pd.DataFrame({'x':x, 'y':y, 'course':course, 'stamina':stamina}))+\
geom_point(aes(x='x',y='y'))+\
geom_line(aes(x='x',y='y',size='stamina',color='course'))
다음은 농구선수 A,B의 시즌별 자유투 성공률이다.
시즌1 | 시즌2 | |
---|---|---|
A선수 | 7/10 | 999999/1000000 |
B선수 | 8/10 | 4/4 |
- 표안의 값은 성공횟수/총자유투시도
?에 적절한 값을 채워 시즌 1,2 모두 B선수의 자유투 성공률이 높지만 시즌1-2를 전체 합치면 A선수의 자유투 성공률이 더 높도록 하라. (즉 ?에 적절한 값을 채워 심슨의 역설을 설명하기 위한 자료를 구성하라.)
만들어진 자료를 바탕으로 심슨의 역설을 시각화하라. (즉 시즌 1,2의 자유투 성공률과 전체 자유투 성공률을 barplot으로 시각화하라)
- 내 Answer
season=(['season1']*2+['season2']*2+['season1']*2+['season2']*2)
player=['A']*4+['B']*4
STATE=['WIN','LOSE']*4
COUNT=[7,3,999999,1,8,2,4,0]
df=pd.DataFrame({'season':season,'STATE':STATE,'player':player,'COUNT':COUNT})
df
_df1=df.groupby(by=['player','STATE']).agg({'COUNT':np.sum}).reset_index()
_df2=df.groupby(by='player').agg({'COUNT':np.sum}).reset_index().rename(columns={'COUNT':'SUM'})
td=pd.merge(_df1,_df2)
td['PROP']=td.COUNT/td.SUM
ggplot(td.query('STATE=="WIN"'))+geom_bar(aes(x='player',y='PROP',fill='player'),stat='identity')
td=df.groupby(['season','player']).agg({'COUNT':sum}).reset_index().rename(columns={'COUNT':'SUM'}).merge(df)
td['PROP']=td.COUNT/td.SUM
ggplot(td.query('STATE=="WIN"'))+geom_bar(aes(x='player',y='PROP',fill='player'),stat='identity')+facet_wrap('season')