title: How do I force clustering of data in a specific evident pattern?
body: <p>I have a large set of 'Vehicle speed vs Engine RPM' values for a vehicle. I'm try to predict the time spent by the vehicle on each gear.</p>
  
  <p>I ran K-Means clustering on the dataset and got the following result:
  <a href="https://i.stack.imgur.com/QZHf8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QZHf8.png" alt="Vehicle Speed vs Engine RPM (~86000 points)"></a></p>
  
  <p>Clearly, my algorithm has failed to capture the evident pattern. I want to force K-Means (or any other clustering algorithm, for that matter) to cluster data along the six sloped lines. Snippet of relevant code:</p>
  
  <pre><code>import numpy as np
  import pandas as pd
  from matplotlib import pyplot as plt
  from sklearn.cluster import KMeans
  
  plt.rcParams['figure.figsize'] = (16, 9)
  plt.style.use('ggplot')
  
  # Importing the dataset
  data = pd.read_csv('speedRpm.csv')
  print(data.shape)
  data.head()
  
  # Getting the data points
  f1 = data['rpm'].values
  f2 = data['speed'].values
  X = np.array(list(zip(f1, f2)))
  
  # Number of clusters
  k = 5
  
  kmeans = KMeans(n_clusters=k)
  # Fitting the input data
  kmeans = kmeans.fit(X)
  # Getting the cluster labels
  labels = kmeans.predict(X)
  # Centroid values
  centroids = kmeans.cluster_centers_
  
  labeled_array = {i: X[np.where(kmeans.labels_ == i)] for i in range(kmeans.n_clusters)}
  
  colors = ['r', 'g', 'b', 'y', 'c']
  fig, ax = plt.subplots()
  for i in range(k):
          points = np.array([X[j] for j in range(len(X)) if kmeans.labels_[j] == i])
          ax.scatter(points[:, 0], points[:, 1], s=7, c=colors[i])
  ax.scatter(centroids[:, 0], centroids[:, 1], marker='*', s=200, c='#050505')
  
  plt.show()
  </code></pre>
  
  <p>How do I make sure the clustering algorithm captures the right pattern, even though it possibly isn't the most efficient?</p>
  
  <p>Thanks!</p>
  
  <p><strong>EDIT</strong>:</p>
  
  <p>Ran the same set of points using DBSCAN this time. After playing around with the <code>eps</code> and <code>min_samples</code> values for sometime, got the following result:</p>
  
  <p><a href="https://i.stack.imgur.com/P6sIR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/P6sIR.png" alt="enter image description here"></a> </p>
  
  <p>Although, still not perfect and way too many outliers, the algorithm is beginning to capture the linear trend.</p>
  
  <p>Code:</p>
  
  <pre><code>import numpy as np
  import pandas as pd
  from matplotlib import pyplot as plt
  from sklearn.cluster import KMeans
  from sklearn.cluster import DBSCAN
  
  plt.rcParams['figure.figsize'] = (16, 9)
  plt.style.use('ggplot')
  
  # Importing the dataset
  data = pd.read_csv('speedRpm.csv')
  print(data.shape)
  data.head()
  
  # Getting the values and plotting it
  f1 = data['rpm'].values
  f2 = data['speed'].values
  X = np.array(list(zip(f1, f2)))
  
  # DBSCAN
  
  # Compute DBSCAN
  db = DBSCAN(eps=1.1, min_samples=3).fit(X)
  core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
  core_samples_mask[db.core_sample_indices_] = True
  labels = db.labels_
  
  # Number of clusters in labels, ignoring noise if present.
  n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
  print "Estimated Number of Clusters", n_clusters_
  
  # Black removed and is used for noise instead.
  unique_labels = set(labels)
  colors = [plt.cm.Spectral(each)
            for each in np.linspace(0, 1, len(unique_labels))]
  for k, col in zip(unique_labels, colors):
      if k == -1:
          # Black used for noise.
          col = [0, 0, 0, 1]
  
      class_member_mask = (labels == k)
  
      xy = X[class_member_mask &amp; core_samples_mask]
      plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
               markeredgecolor='k', markersize=14)
  
      xy = X[class_member_mask &amp; ~core_samples_mask]
      plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
               markeredgecolor='k', markersize=6)
  
  plt.title('Estimated number of clusters: %d' % n_clusters_)
  plt.show()
  </code></pre>