<commit_before>angular.module('cluster-data', [])
.factory('kmeans', [function(){

  function Kmeans(k, data, coordsKey){
    this.k = k;
    this.coordsKey = coordsKey;
    this.data = data;
    this.extremes = this.getDataExtremes();
    this.ranges = this.getDataRanges();
    this.means = this.initMeans();
    this.clusters = this.assignCentroids();
    // this.changed = false;
    // this.moveMeans();
  }

  Kmeans.prototype.run = function(){
    this.moveMeans();
  };

  Kmeans.prototype.recalculate = function(){
    this.extremes = this.getDataExtremes();
    this.ranges = this.getDataRanges();
    this.means = this.initMeans();
    this.groups = this.assignCentroids();
  };

  Kmeans.prototype.getDataExtremes = function(){
    var data = this.data;
    var coordsKey = this.coordsKey;
    var extremes = [];

    for (var i in data){
      //if coordsKey on data given use that, else just data
      var point = coordsKey ? data[i][coordsKey] : data[i];
      //generic for n dimensional data
      for (var dimension in point){
        if ( ! extremes[dimension] ){
          extremes[dimension] = {min: 1000, max: 0};
        }
        if (point[dimension] < extremes[dimension].min){
          extremes[dimension].min = point[dimension];
        }
        if (point[dimension] > extremes[dimension].max){
          extremes[dimension].max = point[dimension];
        }
      }

    }
    return extremes;
  };

  Kmeans.prototype.getDataRanges = function(){
    var ranges = [];
    var extremes = this.extremes;

    for (var dimension in extremes){
      ranges[dimension] = extremes[dimension].max - extremes[dimension].min;
    }

    return ranges;
  };

  Kmeans.prototype.initMeans = function(){
    var dataExtremes = this.extremes;
    var dataRanges = this.ranges
    var k = this.k;
    var data = this.data;
    var means = [];
    while (k--){
      var mean = [];
      for (var dimension in dataExtremes){
        mean[dimension] = dataExtremes[dimension].min + ( Math.random() * dataRanges[dimension] );
      }
      means.push(mean);
    }

    return means;
  };

  Kmeans.prototype.assignCentroids = function() {
    var data = this.data;
    var means = this.means;
    var coordsKey = this.coordsKey;
    var assignments = {};
    for (var i = data.length - 1; i >= 0; i--){
      var point = coordsKey ? data[i][coordsKey] : data[i];
      var distances = [];

      for (var j = means.length - 1; j >= 0; j--) {
        var mean = means[j];
        var sum = 0;

        for (var dimension in point){
          var difference = point[dimension] - mean[dimension];
          difference *= difference;
          sum += difference;
        }

        distances[j] = Math.sqrt(sum);
      }

      assignments[i] = distances.indexOf( Math.min.apply(null, distances) );
    }
    return assignments;
  };

  Kmeans.prototype.moveMeans = function(){
    var means = this.means;
    var assignments = this.clusters;
    var dataExtremes = this.extremes;
    var sums = Array( means.length );
    var counts = Array( means.length );

    this.changed = false;
    for (var i = means.length - 1; i >= 0; i--) {
      counts[i] = 0;
      sums[i] = Array( means[i].length );
      for (var dimension in means[i])
      {
        sums[i][dimension] = 0;
      }
    }

    for (var point_index = assignments.length - 1; point_index >= 0; point_index--) {
      var dataRanges = this.ranges;
      var mean_index = assignments[point_index];
      var point = data[point_index];
      var mean = means[mean_index];

      counts[mean_index]++;
      for (var dimension = mean.length - 1; dimension >= 0; dimension--) {
        sums[mean_index][dimension] += point[dimension];
      }
    }

    for (var mean_index in sums){
      console.log(counts[mean_index]);
      if ( 0 === counts[mean_index] ){
        sums[mean_index] = means[mean_index];
        // Mean with no points

        for (var dimension in dataExtremes){
          sums[mean_index][dimension] = dataExtremes[dimension].min + ( Math.random() * dataRanges[dimension] );
        }
        continue;
      }

      for (var dimension in sums[mean_index]){
        sums[mean_index][dimension] /= counts[mean_index];
      }
    }

    //one day replace this with Object.observer ;) ECMAScript6
    if (means.toString() !== sums.toString()){
      this.changed = true;
    }

    return sums;
  };

  return Kmeans;
}]);<commit_msg>impliments kmeans clustering<commit_after>angular.module('cluster-data', [])
.factory('kmeans', [function(){

  function Kmeans(data, k, coordsKey){
    this.k = k;
    this.coordsKey = coordsKey;
    this.data = data;
    this.extremes = this.getDataExtremes();
    this.ranges = this.getDataRanges();
    this.means = this.initMeans();
    this.assignments = this.assignCentroids();
    this.clusters = this.getClusterArray();
    this.changed = false;
    this.run();
  }

  Kmeans.prototype.run = function(){
    this.moveMeans();
    while(this.changed){
      this.moveMeans();
    }
  };

  Kmeans.prototype.recalculate = function(data, k){
    this.k = k ? data : this.k;
    this.data = data ? data : this.data;
    this.extremes = this.getDataExtremes();
    this.ranges = this.getDataRanges();
    this.means = this.initMeans();
    this.groups = this.assignCentroids();
    this.clusters = this.getclusterArray();
    this.run()
  };

  Kmeans.prototype.getDataExtremes = function(){
    var data = this.data;
    var coordsKey = this.coordsKey;
    var extremes = [];

    for (var i in data){
      //if coordsKey on data given use that, else just data
      var point = coordsKey ? data[i][coordsKey] : data[i];
      //generic for n dimensional data
      for (var dimension in point){
        if ( ! extremes[dimension] ){
          extremes[dimension] = {min: 1000, max: 0};
        }
        if (point[dimension] < extremes[dimension].min){
          extremes[dimension].min = point[dimension];
        }
        if (point[dimension] > extremes[dimension].max){
          extremes[dimension].max = point[dimension];
        }
      }

    }
    return extremes;
  };

  Kmeans.prototype.getDataRanges = function(){
    var ranges = [];
    var extremes = this.extremes;

    for (var dimension in extremes){
      ranges[dimension] = extremes[dimension].max - extremes[dimension].min;
    }

    return ranges;
  };

  Kmeans.prototype.initMeans = function(){
    var dataExtremes = this.extremes;
    var dataRanges = this.ranges
    var k = this.k;
    var data = this.data;
    var means = [];
    while (k--){
      var mean = [];
      for (var dimension in dataExtremes){
        mean[dimension] = dataExtremes[dimension].min + ( Math.random() * dataRanges[dimension] );
      }
      means.push(mean);
    }

    return means;
  };

  Kmeans.prototype.assignCentroids = function() {
    var mean, difference, sum;
    var data = this.data;
    var means = this.means;
    var coordsKey = this.coordsKey;
    var assignments = {};
    for (var i = data.length - 1; i >= 0; i--){
      var point = coordsKey ? data[i][coordsKey] : data[i];
      var distances = [];

      //Calculate Cartesian distances with Pythagorean theorem 
      for (var j = means.length - 1; j >= 0; j--) {
        mean = means[j];
        sum = 0;

        for (var dimension in point){
          difference = point[dimension] - mean[dimension];
          difference *= difference;
          sum += difference;
        }

        distances[j] = Math.sqrt(sum);
      }

      assignments[i] = distances.indexOf( Math.min.apply(null, distances) );
    }
    return assignments;
  };

  Kmeans.prototype.moveMeans = function(){
    var means = this.means;
    var assignments = this.assignments;
    var dataExtremes = this.extremes;
    var dataRanges = this.ranges;
    var sums = Array( means.length );
    var counts = Array( means.length );

    for (var i = means.length - 1; i >= 0; i--) {
      counts[i] = 0;
      sums[i] = Array( means[i].length );
      for (var dimension in means[i])
      {
        sums[i][dimension] = 0;
      }
    }

    for (var point_index = assignments.length - 1; point_index >= 0; point_index--) {
      var dataRanges = this.ranges;
      var mean_index = assignments[point_index];
      var point = data[point_index];
      var mean = means[mean_index];

      counts[mean_index]++;
      for (var dimension = mean.length - 1; dimension >= 0; dimension--) {
        sums[mean_index][dimension] += point[dimension];
      }
    }

    for (var mean_index in sums){
      console.log(counts[mean_index]);
      if ( 0 === counts[mean_index] ){
        sums[mean_index] = means[mean_index];
        // Mean with no points

        for (var dimension in dataExtremes){
          sums[mean_index][dimension] = dataExtremes[dimension].min + ( Math.random() * dataRanges[dimension] );
        }
        continue; //skip subsequent for loop as no points in
      }

      for (var dimension in sums[mean_index]){
        sums[mean_index][dimension] /= counts[mean_index];
      }
    }

    //one day replace this with Object.observer ;) ECMAScript6
    if (means.toString() !== sums.toString()){
      this.changed = true;
    }

    this.means = sums;
  };

  Kmeans.prototype.getClusterArray = function(){
    var assignments = this.assignments;
    var data = this.data;
    var clusters = {};
    for (var i = data.length - 1; i >= 0; i--) {
      clusters[assignments[i]] = data[i];
    };
  };
  return Kmeans;
}]);
{'fraction_non_alphanumeric': 0.13833825390130747, 'fraction_numerical': 0.004428511176718684, 'mean_word_length': 2.4045226130653266, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3733743', 'n_tokens_mistral': 3145, 'n_tokens_neox': 2970, 'n_words': 710}