아이티윌_데이터 분석 55기/문제풀이_통계 및 분석

#13-2. 13일차 퀴즈에 대한 문제풀이

ecosso 2026. 4. 29. 17:16

 [ 연습문제 - 군집분석 ]
 cancer.csv 파일의 설명변수(id제외)만 사용하여 계층/비계층 군집분석을 진행
 단, 변수 스케일링 후 군집분석을 진행하세요

 

더보기

[ 내 답변 ]

 

df <- read.csv('cancer.csv')
df$id <- NULL
head(df)
str(df)

# 변수 스케일링
f1 <- function(x) {
  (x - mean(x)) / sd(x)
}

df[,-1] <- apply(df[,-1], 2, f1)
head(df)


# 계층적 군집분석
# 거리행렬 구하기
x <- df[,-1]
d1 <- dist(x)

# 학습
m1<- hclust(d1, method = 'single')          # 최단거리법
m2<- hclust(d1, method = 'complete')    # 최장거리법
m3<- hclust(d1, method = 'centroid')      # 중심연결법
m4<- hclust(d1, method = 'average')      # 평균연결법
m5<- hclust(d1, method = 'ward.D')       # 와드연결법 (와드 1)
m6<- hclust(d1, method = 'ward.D2')     # 와드연결법 (와드 2)


# 시각화
dev.new()
par(mfrow=c(2,3))

# 최단거리법
plot(m1, hang = -1, main = 'Single')


# 최장거리법
plot(m2, hang = -1, main = 'Complete')


# 중심연결법
plot(m3, hang = -1, main = 'Centroid')

# 평균연결법
plot(m4, hang = -1, main = 'Average')

# 와드연결법 (와드1)
plot(m5, hang = -1, main = 'Ward.D')

# 와드연결법 (와드2)
plot(m6, hang = -1, main = 'Ward.D2')


# 군집 수 구하기
result <- NbClust(data = x, min.nc=2, max.nc = 15, method = 'ward.D')
result

> result <- NbClust(data = x, min.nc=2, max.nc = 15, method = 'ward.D')
*** : The Hubert index is a graphical method of determining the number of clusters.
                In the plot of Hubert index, we seek a significant knee that corresponds to a 
                significant increase of the value of the measure i.e the significant peak in Hubert
                index second differences plot. 
 
*** : The D index is a graphical method of determining the number of clusters. 
                In the plot of D index, we seek a significant knee (the significant peak in Dindex
                second differences plot) that corresponds to a significant increase of the value of
                the measure. 
 
******************************************************************* 
* Among all indices:                                                
* 7 proposed 2 as the best number of clusters 
* 7 proposed 3 as the best number of clusters 
* 2 proposed 5 as the best number of clusters 
* 1 proposed 10 as the best number of clusters 
* 2 proposed 11 as the best number of clusters 
* 1 proposed 14 as the best number of clusters 

                   ***** Conclusion *****                            
 
* According to the majority rule, the best number of clusters is  2 
 
 
******************************************************************* 

 

result <- NbClust(data = x, min.nc=2, max.nc = 15, method = 'ward.D2')
result

> result <- NbClust(data = x, min.nc=2, max.nc = 15, method = 'ward.D2')
*** : The Hubert index is a graphical method of determining the number of clusters.
                In the plot of Hubert index, we seek a significant knee that corresponds to a 
                significant increase of the value of the measure i.e the significant peak in Hubert
                index second differences plot. 
 
*** : The D index is a graphical method of determining the number of clusters. 
                In the plot of D index, we seek a significant knee (the significant peak in Dindex
                second differences plot) that corresponds to a significant increase of the value of
                the measure. 
 
******************************************************************* 
* Among all indices:                                                
* 9 proposed 2 as the best number of clusters 
* 6 proposed 3 as the best number of clusters 
* 1 proposed 5 as the best number of clusters 
* 2 proposed 7 as the best number of clusters 
* 1 proposed 12 as the best number of clusters 
* 1 proposed 13 as the best number of clusters 

                   ***** Conclusion *****                            
 
* According to the majority rule, the best number of clusters is  2 
 
 
******************************************************************* 

 


# 비계층적 군집분석 

withss <- c() ; betss <- c()
for (i in 2:10) {
  set.seed(0)
  m2 <- kmeans(x, i)
  withss <- c(withss, m2$tot.withinss)
  betss <- c(betss, m2$betweenss)
}

par(mfrow = c(1,2))
plot(2:10, withss, xlab = 'k',
     ylab = 'within_ss', type = 'o')
plot(2:10, betss, xlab = 'k',
     ylab = 'between_ss', type = 'o')

 

 

set.seed(0)
m2 <- kmeans(x, 2)

> m2
K-means clustering with 2 clusters of sizes 375, 194

Cluster means:
  radius_mean texture_mean perimeter_mean  area_mean
1  -0.4825702   -0.2388313     -0.4999790 -0.4777212
2   0.9328033    0.4616584      0.9664542  0.9234301
  smoothness_mean compactness_mean concavity_mean
1      -0.3107301       -0.5255563     -0.5785267
2       0.6006381        1.0158949      1.1182861
  concave_points_mean symmetry_mean fractal_dimension_mean
1           -0.586655    -0.3088121             -0.1490098
2            1.133998     0.5969307              0.2880344
   radius_se  texture_se perimeter_se    area_se smoothness_se
1 -0.4276089 -0.02109138   -0.4305928 -0.4013983   -0.02381032
2  0.8265636  0.04076942    0.8323315  0.7758988    0.04602510
  compactness_se concavity_se concave_points_se symmetry_se
1     -0.3698751   -0.3343034        -0.3973627  -0.0748643
2      0.7149647    0.6462051         0.7680980   0.1447119
  fractal_dimension_se radius_worst texture_worst perimeter_worst
1           -0.2366141   -0.5173986    -0.2512569      -0.5318435
2            0.4573726    1.0001262     0.4856771       1.0280479
  area_worst smoothness_worst compactness_worst concavity_worst
1 -0.4989187       -0.3158003        -0.4918085      -0.5363714
2  0.9644047        0.6104387         0.9506607       1.0368003
  concave_points_worst symmetry_worst fractal_dimension_worst
1            -0.579591     -0.3030883              -0.3364329
2             1.120343      0.5858665               0.6503213

Clustering vector:
  [1] 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 2 2 2 2 2 2 2 2
 [31] 2 2 2 2 2 2 2 1 1 1 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 2 2 1 1
 [61] 1 1 2 1 2 2 1 1 2 1 2 1 2 1 1 2 1 2 2 1 1 2 2 2 1 2 1 2 1 2
 [91] 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 1 2 1 1 1 1 2 2 1
[121] 1 2 2 1 1 1 1 2 2 2 1 2 2 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1
[151] 1 1 2 1 1 1 2 1 1 1 1 2 2 1 2 1 1 2 2 1 1 1 2 1 1 1 2 2 1 1
[181] 2 2 1 1 1 1 1 1 1 1 2 1 1 2 2 1 2 2 2 2 1 2 2 2 1 1 1 1 1 1
[211] 2 1 2 2 2 2 1 1 2 2 1 1 1 2 1 1 1 1 1 2 2 1 1 2 1 1 2 2 1 2
[241] 1 1 2 1 2 1 1 2 1 1 2 1 2 2 2 1 2 2 2 2 2 1 2 1 2 2 1 1 1 1
[271] 1 1 2 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
[301] 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 1 2 1 2 1 1 1 1 2 2
[331] 2 1 1 1 1 2 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1
[361] 1 1 1 1 1 2 2 1 2 2 2 1 2 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 2
[391] 1 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1
[421] 1 2 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 1 2 1 1 1 1 2 1 1 2
[451] 1 2 1 1 1 1 1 1 1 1 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 2
[481] 1 1 1 1 1 2 1 2 1 1 1 1 2 1 1 1 1 1 2 2 1 2 1 2 2 2 1 1 1 2
[511] 1 1 2 1 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 1
[541] 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1

Within cluster sum of squares by cluster:
[1] 4971.437 6603.711
 (between_SS / total_SS =  32.1 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"    
[5] "tot.withinss" "betweenss"    "size"         "iter"        
[9] "ifault"   

 

# 군집은 2개 (샘플사이즈는 각 375, 194)

# between_ss / total_ss = 32.1%

 

 

m2 <- kmeans(x, 3)
m2

> m2
K-means clustering with 3 clusters of sizes 110, 100, 359

Cluster means:
  radius_mean texture_mean perimeter_mean  area_mean
1   1.6176587    0.6260620      1.6225732  1.6616915
2  -0.1721774    0.1788294     -0.1006558 -0.2198210
3  -0.4477011   -0.2416428     -0.4691295 -0.4479219
  smoothness_mean compactness_mean concavity_mean
1       0.3982143        0.9297963      1.2382477
2       0.8484791        1.0345212      0.7803190
3      -0.3583607       -0.5730633     -0.5967664
  concave_points_mean symmetry_mean fractal_dimension_mean
1           1.4856628     0.4317906             -0.2866671
2           0.4989880     0.7521312              1.1829407
3          -0.5942109    -0.3418108             -0.2416732
    radius_se  texture_se perimeter_se    area_se smoothness_se
1  1.44001760  0.09373762   1.40414509  1.4222534   -0.07260779
2 -0.08495483  0.02338187  -0.01781494 -0.1722055    0.43926501
3 -0.41756672 -0.03523489  -0.42527706 -0.3878199   -0.10011043
  compactness_se concavity_se concave_points_se symmetry_se
1      0.4786511    0.4393663         0.7871419  0.05437929
2      1.0737418    0.8897247         0.7514795  0.28620432
3     -0.4457543   -0.3824590        -0.4505113 -0.09638483
  fractal_dimension_se radius_worst texture_worst perimeter_worst
1            0.1189330   1.66528388     0.5424224     1.655385195
2            1.0255153  -0.08815198     0.3111937    -0.007008775
3           -0.3221007  -0.48569924    -0.2528853    -0.505268785
  area_worst smoothness_worst compactness_worst concavity_worst
1  1.6834662        0.3365925         0.6697022       0.8858320
2 -0.1563397        0.9682984         1.1787346       1.0441360
3 -0.4722766       -0.3728552        -0.5335395      -0.5622705
  concave_points_worst symmetry_worst fractal_dimension_worst
1             1.272063      0.3000824              0.08399194
2             0.742345      0.8092044              1.38339588
3            -0.596550     -0.3173524             -0.41108273

Clustering vector:
  [1] 1 1 1 2 1 2 1 2 2 2 3 2 1 3 2 2 3 2 1 3 3 3 2 1 1 1 2 1 2 1
 [31] 1 2 1 1 2 2 2 3 3 2 3 2 1 2 3 1 3 2 3 3 3 3 3 1 3 3 1 2 3 3
 [61] 3 3 2 3 2 2 3 3 2 3 1 2 2 3 3 1 3 1 1 3 3 2 1 1 3 1 3 1 3 2
 [91] 3 3 3 3 2 1 3 3 3 2 3 3 3 3 3 2 3 3 1 3 3 2 2 3 3 3 3 2 2 3
[121] 3 1 1 3 3 3 3 1 2 1 3 3 3 3 1 3 3 3 1 3 3 3 3 3 3 2 2 3 3 3
[151] 3 2 2 3 3 3 1 3 3 3 3 1 1 3 1 3 3 3 1 3 3 3 2 3 3 3 2 2 3 3
[181] 1 1 3 3 3 3 3 3 3 3 2 3 3 2 2 3 2 1 1 2 3 1 1 2 3 3 3 3 2 3
[211] 1 3 1 2 2 2 2 3 1 1 3 3 3 2 3 3 3 3 3 2 2 3 3 1 3 3 1 1 3 1
[241] 3 3 2 3 1 3 3 2 3 3 1 3 1 3 1 3 1 2 1 2 1 3 1 3 1 1 3 3 3 2
[271] 3 3 1 3 3 3 3 3 3 3 1 3 1 2 3 3 3 3 2 3 2 3 3 3 3 3 3 3 3 3
[301] 1 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 2 3 3 1 3 1 3 3 3 3 2 2
[331] 2 3 3 3 3 1 3 1 3 1 3 3 3 1 3 3 3 3 3 3 3 2 1 2 3 3 2 3 3 3
[361] 3 3 3 3 3 1 1 3 1 1 2 3 1 1 3 3 2 3 3 2 3 3 3 2 3 3 3 3 2 1
[391] 3 3 2 1 3 3 3 3 3 3 2 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3 1 3 3
[421] 3 2 3 3 3 3 3 3 3 3 2 3 1 1 3 2 3 3 3 3 2 1 3 3 3 3 1 3 3 1
[451] 3 1 3 3 3 3 3 3 3 3 1 1 3 3 3 2 3 3 1 2 3 3 3 3 3 3 3 3 3 2
[481] 3 3 3 3 3 2 3 1 3 3 3 3 1 3 3 3 2 3 1 1 3 2 3 1 2 2 3 2 3 2
[511] 3 3 2 3 3 3 1 1 3 3 2 1 3 3 3 3 3 3 3 3 3 3 3 1 3 1 3 2 3 2
[541] 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 1 1 1 3 1 3

Within cluster sum of squares by cluster:
[1] 2894.489 2791.854 4357.771
 (between_SS / total_SS =  41.1 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"    
[5] "tot.withinss" "betweenss"    "size"         "iter"        
[9] "ifault" 

# 군집은 3개 (샘플사이즈는 각 110, 100, 359)

# between_ss / total_ss = 41.1%

 

[ 문제풀이 ]

 

# STEP1: 데이터 로딩)
cancer <- read.csv('cancer.csv')
cancer$diagnosis <- factor(cancer$diagnosis)

# STEP2: 불필요 변수 제거)
cancer$id <- NULL

# STEP3: 스케일링
cancer[,-1] <- scale(cancer[,-1])

# STEP4: 계층적 군집분석 수행)
X <- cancer[,-1]
d1 <- dist(X)

# 학습
m1 <- hclust(d1, method = 'single')    # 최단거리법
m2 <- hclust(d1, method = 'complete')  # 최장거리법
m3 <- hclust(d1, method = 'centroid')  # 중심연결법
m4 <- hclust(d1, method = 'average')   # 평균연결법
m5 <- hclust(d1, method = 'ward.D')    # 와드1
m6 <- hclust(d1, method = 'ward.D2')   # 와드2

# 시각화
dev.new()
par(mfrow=c(2,3))
plot(m1, hang = -1, main = 'Single')
rect.hclust(m1, k = 2)

plot(m2, hang = -1, main = 'Complete')
rect.hclust(m2, k = 2)

plot(m3, hang = -1, main = 'Centroid')
rect.hclust(m3, k = 2)

plot(m4, hang = -1, main = 'Average')
rect.hclust(m4, k = 2)

plot(m5, hang = -1, main = 'Ward.D')
rect.hclust(m5, k = 2)

plot(m6, hang = -1, main = 'Ward.D2')
rect.hclust(m6, k = 2)

# 평가
library(NbClust)  

result <- NbClust(data = X,           # 데이터
                  min.nc = 2,         # 최소군집수
                  max.nc = 10,        # 최대군집수
                  method = 'ward.D') # 군집간 거리

result
# ******************************************************************* 
#   * Among all indices:                                                
#   * 8 proposed 2 as the best number of clusters 
# * 7 proposed 3 as the best number of clusters 
# * 2 proposed 5 as the best number of clusters 
# * 1 proposed 7 as the best number of clusters 
# * 2 proposed 10 as the best number of clusters 

# ***** Conclusion *****                            
#   
#   * According to the majority rule, the best number of clusters is  2 



# STEP4: 비계층적 군집분석 수행)
set.seed(0)
m1 <- kmeans(X, 2)
m1