Как отредактировать собственную функцию k-средних, чтобы она принимала кластеры в качестве входных данных вместо центров в R?

#r #function

#r #функция

Вопрос:

Как можно отредактировать эту функцию, чтобы использовать ‘k’ (количество кластеров) в качестве входных данных вместо центров, как это имеет место в настоящее время? Код приведен ниже:

 # Calculates Eudlidean distance
euclid <- function(points1, points2) {
  distanceMatrix <- matrix(NA, nrow=dim(points1)[1], ncol=dim(points2)[1])
  for(i in 1:nrow(points2)) {
    distanceMatrix[,i] <- sqrt(rowSums(t(t(points1)-points2[i,])^2))
  }
  distanceMatrix
}

# k-means algorithm
k_means = function(x, centers, distFun) {
  prevClusters = NULL
  prevCenters = NULL
  
  repeat {
    distsToCenters = distFun(x, centers)
    clusters = apply(distsToCenters, 1L, which.min)
    centers = apply(x, 2L, tapply, clusters, mean) # If I replace 'mean' here with 'centroid', error comes
    if (identical(prevClusters, clusters)) break
    
    prevClusters = clusters
    prevCenters = centers
  }
  
  list(clusters = clusters, centers = centers)
}

test=data # A data.frame
ktest=as.matrix(test) # Turn into a matrix
centers <- ktest[sample(nrow(ktest), 5),] # Sample some centers, 5 for example

res <- k_means(ktest, centers, euclid) 
print(res)
 

Результатом при использовании матрицы данных в качестве входных данных является количество кластеров, за которыми следуют их центры. Можно ли отредактировать это так, чтобы вместо желаемого количества центров вы вводили желаемое количество кластеров? Т.е. как можно определить «кластеры», чтобы их можно было использовать в качестве входных данных?

Комментарии:

1. В чем разница между количеством центров и количеством кластеров? Разве у каждого кластера нет центра?

Ответ №1:

Прежде всего, я бы посоветовал вам не изобретать велосипед, поскольку R предоставляет готовую kmeans реализацию. Однако, если в вашей функции вам просто указано количество кластеров, вы можете случайным образом выбирать точки внутри диапазона ваших данных. Что-то вроде:

 if (length(centers)==1) {
    k<-as.integer(centers)
    extrema<-apply(x,2,range)
    centers<-apply(extrema,2,function(.x) runif(k,.x[1],.x[2])) 
}
 

rigth в начале вашей функции.