如何从其他列表中向列表添加元素?

时间:2017-03-08 22:29:18

标签: python mean k-means nested-lists

代码找到每个列表中的最小项,我想将该数据点添加到基于的列表中 列表来自。我也希望能够找到每个集群的平均值。

import numpy as np

centroids = np.array([[3,44],[5,15],[99,12]])
dataPoints = np.array([[2,4],[17,4],[45,2],[45,7],[16,32],[32,14],[20,56],[68,33]])

def size(vector):
    return np.sqrt(sum(x**2 for x in vector))

def distance(vector1, vector2):
    return size(vector1 - vector2)

def distances(array1, array2):
    lists = [[distance(vector1, vector2) for vector2 in array2] for vector1 in array1]
    x = 1
    for i in lists:
        print ('Distance from Centroid {}:{}\n'.format(x,i))
        x=x+1

    print map(min, zip(*lists))

distances(centroids,dataPoints)

我的输出:

Distance from Centroid 1:[40.01249804748511, 42.379240200834182, 59.396969619669989, 55.97320787662612, 17.691806012954132, 41.725292090050132, 20.808652046684813, 65.924198895398035]

Distance from Centroid 2:[11.401754250991379, 16.278820596099706, 42.059481689626182, 40.792156108742276, 20.248456731316587, 27.018512172212592, 43.657759905886145, 65.520989003524662]

Distance from Centroid 3:[97.329337817535773, 82.389319696183918, 54.918120870983927, 54.230987451824994, 85.37564055396598, 67.029844099475568, 90.426765949026404, 37.443290453698111]

[11.401754250991379, 16.278820596099706, 42.059481689626182, 40.792156108742276, 17.691806012954132, 27.018512172212592, 20.808652046684813, 37.443290453698111]

其他期望的输出:

Cluster 1: [[16,32],[20,56]]
Cluster 2: [[2,4],[17,4],[45,2],[45,7],[32,14]]
Cluster 3: [[68,33]]

List of means :[[18,44],[28.2,6.2],[68,33]]

对于此示例,定义了质心/簇的数量。 如果它们是动态的并且需要动态创建群集列表怎么办?

1 个答案:

答案 0 :(得分:1)

假设您处于一般情况,您想告诉“从哪个列表中压缩元素来自哪个”,那么,您必须跟踪它:

>>> import random
>>> from pprint import pprint
>>> ls = [[random.randint(80,200) for _ in range(8)] for _ in range(3)]
>>> pprint(ls)
[[114, 196, 185, 192, 129, 183, 150, 189],
 [173, 173, 116, 135, 109, 87, 80, 88],
 [159, 173, 139, 189, 100, 107, 102, 188]]
>>> [min(zip(l,range(len(l)))) for l in zip(*ls)]
[(114, 0), (173, 1), (116, 1), (135, 1), (100, 2), (87, 1), (80, 1), (88, 1)]

适用于您的情况:

>>> import numpy as np
>>>
>>> centroids = np.array([[3,44],[5,15],[99,12]])
>>> dataPoints = np.array([[2,4],[17,4],[45,2],[45,7],[16,32],[32,14],[20,56],[68,33]])
>>>
>>> def size(vector):
...     return np.sqrt(sum(x**2 for x in vector))
...
>>> def distance(vector1, vector2):
...     return size(vector1 - vector2)
...
>>> lists = [[distance(vector1, vector2) for vector2 in dataPoints] for vector1 in centroids]
>>> pprint(lists)
[[40.01249804748511,
  42.379240200834182,
  59.396969619669989,
  55.97320787662612,
  17.691806012954132,
  41.725292090050132,
  20.808652046684813,
  65.924198895398035],
 [11.401754250991379,
  16.278820596099706,
  42.059481689626182,
  40.792156108742276,
  20.248456731316587,
  27.018512172212592,
  43.657759905886145,
  65.520989003524662],
 [97.329337817535773,
  82.389319696183918,
  54.918120870983927,
  54.230987451824994,
  85.37564055396598,
  67.029844099475568,
  90.426765949026404,
  37.443290453698111]]
>>> smallest = [min(zip(l,range(len(l)))) for l in zip(*lists)]
>>> smallest
[(11.401754250991379, 1), (16.278820596099706, 1), (42.059481689626182, 1), (40.792156108742276, 1), (17.691806012954132, 0), (27.018512172212592, 1), (20.808652046684813, 0), (37.443290453698111, 2)]

我们本来可以聪明而且不带最小值,但这并不重要。

由于您可能拥有尽可能多的centriods,为了使其动态化,请不要使用变量,请使用容器。列表可以,但dict很简单:

>>> clusters = {}
>>> for j, (_, i) in enumerate(smallest):
...     clusters.setdefault(i,[]).append(dataPoints[j])
...

最后,

>>> pprint(clusters)
{0: [array([16, 32]), array([20, 56])],
 1: [array([2, 4]),
     array([17,  4]),
     array([45,  2]),
     array([45,  7]),
     array([32, 14])],
 2: [array([68, 33])]}

最后,我会坚持使用列表或np.arrays 。两者都很合适。您应该了解每个的优缺点,因此您知道哪个是适合您的问题的数据结构。这是编写代码的一个非常重要的方面。