2017-03-08 10 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]] 

この例では、重心/クラスタの量が定義されています。 動的で、クラスタリストをオンザフライで作成する必要がある場合はどうなりますか?

>>> 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)] 

応用:

+1

これらは*配列*です。 *リストはありません。または少なくとも、あなたは2つを混ぜているようです。なぜリストにこだわるだけではないのですか? –

+0

@ juanpa.arrivillagaタイプ(リスト)をチェックすると、値 'list'が返されます。私は数が少ない配列から始めていることを知っています。あなたのコンセプトでは、問題の解決には、いずれかを使用して、他の利点を持っていますか? – cparks10

+0

@Yes、 'lists'は* list-comprehension *の結果を代入するのでリストになります。あなたが何をしようとしているのか分かりません。 –

答えて

1

と仮定、あなたは「要素はどこから来たのzip圧縮されているリストそこから」は、よく、あなたがそれを追跡するために持っているあなたが伝えたい一般的な状況にあります自分の状況に:

>>> 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 clusters.items()}'。 –

+0

@ juanpa.arrivillagaもし私がただキーではなく値を返すのであれば?したがって、{0:array([18,44])、1:array([2,4])、2:array([41,12])}の代わりに[[18,44]、[ 2,4]、[41,12]]や、元のセントロイド配列/リストによる手段を比較するために使用するのに最適なフォーマットは何ですか? – cparks10

関連する問題