def get_gini(df, label):
gini = 1 - (len(df.loc[df[label] == 'yes'])/len(df))**2 - (len(df.loc[df[label] =='no'])/len(df))**2
return gini
#타겟변수에 대한 값이 yes일때와 no일대 각각 그 확률값을 제고배서 빼주는 방식이므로
#loc을 통해 그 값만 가지는 row들만 추출해서 그 개수를 새는 식으로 함수를 짰습니다
Input: df(데이터), attribute(Gini index를 구하고자 하는 변수명)
해당 결과는 아래와 같이 나와야 합니다.
In [6]:
import itertools # 변수의 모든 클래시 조합을 얻기 위해 itertools 불러오기
def get_binary_split(df, attribute):
'''
이 부분을 채워주세요
'''
a = list(df[attribute].unique())
#타겟변수에 대한 값들이 어떤게 있는지 리스트로 만들기 위해 unique를 사용했습니다
unique =[]
for i in range(len(a)):
unique.append([a[i]])
#각각의 리스트 속 값들을 []또 리스트 안에 넣기 위한 코드입니다
binary = list(itertools.combinations(a,2))
#itertools의 combinations을 사용해서 이진분류로 만들었고
for i in range(len(binary)):
binary[i] = list(map(str,binary[i]))
#각각의 값들을 또 list로 만들었습니다
result = unique+list(binary)
#두개를 합쳐서 이진 분류로 완성
return result
결과로 나온 Dictionary의 Key 값은 해당 class 들로 이루어진 tuple 형태로 들어가 있습니다.
In [8]:
def get_attribute_gini_index(df, attribute, label):
binary_split = get_binary_split(df,attribute)
#위에서 구한 함수를 사용해서 split한 변수들을 list로 받습니다
#(멘토링에서 도움 받음.)
result = {}
for i in binary_split:
unique = list(df[attribute].unique())
#unique함수를 이용해서 각 타겟변수에 대한 값들을 unique로 받습니다
for j in range(len(i)):
if j == 0:
#binary_split에서 'youth'하나만 고려하는 것처럼 그런 경우를 먼저
#그에 해당하는 row들만 뽑아냅니다
new1 = df.loc[df[attribute] == i[j]]
else:
#여러개를 동시에 봐야하는 경우에는 두 경우 모두를 각각 concat으로 더해
#그 경우의 row들만 뽑아냅니다
new1 = pd.concat([new1,df.loc[df[attribute]==i[j]]], axis=0)
gini1 = (len(new1[attribute])/len(df[attribute]))* get_gini(new1,label)
#그래서 앞서 구한 새로운 new data를 통해 gini계수를 구하고 거기에 di/d 확률을 곱해줍니다
# 그다음은 앞서 나눈 것의 나머지 부분을 확인해 gini계수를 구해야하는데
#위에 방식과 똑같이 진행하면 된다
#앞서 확인한 값제외한 걸로 확인을 해야하므로 그걸 확인시켜주기 위해 그걸 지우고!
for k in i:
unique.remove(k)
for s in range(len(unique)):
if s == 0:
new2 = df.loc[df[attribute] == unique[s]]
else:
new2 = pd.concat([new2,df.loc[df[attribute]==unique[s]]], axis = 0)
gini2 = (len(new2[attribute])/len(df[attribute])) *get_gini(new2,label)
#똑같은 방식으로 두번째 gini계수를 구해준다
#앞서 구한 두 gini계수를 더해주면 된다
gini = gini1 + gini2
#결과로 나온 dictionary의 key값은 해당 class들로 이루어진 tuple형태로 되어있으므로 tuple()을 취해준다
result[tuple(i)] = gini
return result
#확인결과 가장 작은 gini index는
#min -> middle_agged -> 0.3571 이므로
#가장 중요한 변수 : age임을 알수 있습니다
In [20]:
##문제3 답안
#문제3) 문제 2에서 제시한 feature로 DataFrame을 split한 후 나눠진 2개의
#DataFrame에서 각각 다음으로 중요한 변수를 선정하고 해당 변수의 Gini index를 제시해주세요
#앞서 구한 가장 중요한 변수를 기반으로
#age, middle_aged / youth,senior 이렇게 나누어 새로운 데이터를 만들었습니다
df1 = pd_data.loc[pd_data['age'] == 'middle_aged']
youth = pd_data.loc[pd_data['age'] == 'youth']
senior = pd_data.loc[pd_data['age'] == 'senior']
df2 = pd.concat([youth,senior],axis=0)
#df1은 이미 모든 target 변수 값이 yes인 완벽하게 split된 데이터이므로 확인할 필요가 없고
#df2를 사용해서 다음으로 중요한 변수를 선정했습니다
#확인결과 가장 작은 gini index 갖는 변수 는 student로
#->{('no',): 0.31999999999999984 가장 낮게 나왔습니다
#한번더 gini index를 확인하면
get_attribute_gini_index(df2, "student", "class_buys_computer")