2017-03-08 119 views
2

该代码找到每个列表中的最小项目,我想将该数据点添加到基于它所来自的列表的 列表中。我也希望能够找到每个群集的均值。如何将元素添加到另一个列表中的列表?

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

@ juanpa.arrivillaga如果我检查类型(列表),它将返回值'列表'。我知道我从numpy数组开始。在你的问题解决方案的概念中,使用哪一个都比另一个有优势? – cparks10

+0

@是的,'lists'将是一个列表,因为它是分配*列表理解*的结果。不过,我不确定你想要做什么。 –

回答

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 s为简单:

>>> 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坚持。很少都适合。而且您应该了解每种方法的优缺点,因此您知道哪个是适合您问题的适当数据结构。这是编写代码非常重要的一个方面。

+0

工程就像一个魅力!我一直在玩弄每个'集群'的平均值,是否有内置的函数可以帮助我呢?我一定会更多关注下次使用的数据类型。 – cparks10

+0

@ cparks10如果你有一个数组列表,这实际上很简单:'means = {k:sum(v)/ len(v)for k,v in clusters.items()}'。 –

+0

@ juanpa.arrivillaga如果我只是想让它返回值而不是键?所以不是{0:array([18,44]),1:array([2,4]),2:array([41,12])}我只会得到[[18,44],[ 2,4],[41,12]]或其他什么是最好的格式来比较手段与原始质心阵列/列表? – cparks10

相关问题