【问题标题】:How to cluster list-of-list by distance condition in Python如何在 Python 中按距离条件对列表列表进行聚类
【发布时间】:2015-01-15 04:18:17
【问题描述】:

我有以下包含 6 个条目的列表:

lol = [['a', 3, 1.01],
       ['x', 5, 1.00],
       ['k', 7, 2.02],
       ['p', 8, 3.00],
       ['b', 10, 1.09], 
       ['f', 12, 2.03]]

lol 中的每个子列表包含 3 个元素:

['a', 3, 1.01]
  e1  e2  e3

上面的列表已经按照e2(即第二个元素)排序

我想大致按照以下步骤“聚类”上述列表:

  1. 选择lol 中最低的条目(wrt.e2)作为第一个集群的键
  2. 将其指定为集群的第一个成员(列表字典)
  3. 计算下一个列表中与第一个成员的差值电流 e3 现有集群。
  4. 如果差值小于阈值,则将该列表指定为 对应集群的成员 否则,使用当前列表作为新键创建新集群。
  5. 重复其余部分直到完成

最终结果将如下所示,阈值

dol = {'a':['a', 'x', 'b'],
       'k':['k', 'f'],
       'p':['p']}

我对此感到困惑,正确的做法是什么:

import json
from collections import defaultdict

thres = 0.1
tmp_e3 = 0
tmp_e1 = "-"

lol = [['a', 3, 1.01], ['x', 5, 1.00], ['k', 7, 2.02],
       ['p', 8, 3.00], ['b', 10, 1.09], ['f', 12, 2.03]]

dol = defaultdict(list)
for thelist in lol:
    e1, e2, e3 = thelist

    if tmp_e1 == "-":
        tmp_e1 = e1
    else:
        diff = abs(tmp_e3 - e3)
        if diff > thres:
            tmp_e1 = e1

    dol[tmp_e1].append(e1)
    tmp_e1 = e1
    tmp_e3 = e3

print json.dumps(dol, indent=4)

【问题讨论】:

  • print json.dumps(dol, indent=4) 给你什么?
  • @Yax: {'a': ['a', 'x'], 'b': ['b'], 'f': ['f'], 'k': ['k'], 'p': ['p']}
  • 对不起,我出去祈祷了。您将通过执行代码来考虑这一点。现在,在您的 else 语句中包含 print diff > thress, thelist 以查看它给出的提示。
  • 记住第一个列表也将满足您的条件,现在将成为 5。
  • OT:我推荐 pprint.pprint(data) 而不是 print json.dumps(data)

标签: python algorithm cluster-analysis


【解决方案1】:

我会首先确保 lol 在第二个元素上排序,然后在列表中迭代只保留第一个元素中不在阈值中的内容:

import json

thres = 0.1
tmp_e3 = 0
tmp_e1 = "-"

lol = [['a', 3, 1.01], ['x',5, 1.00],['k',7, 2.02],
       ['p',8, 3.00], ['b', 10, 1.09], ['f', 12, 2.03]]

# ensure lol is sorted
lol.sort(key = (lambda x: x[1]))
dol = {}

while len(lol) > 0:
    x = lol.pop(0)
    lol2 = []
    dol[x[0]] = [ x[0] ]
    for i in lol:
        if abs(i[2] - x[2]) < thres:
            dol[x[0]].append(i[0])
        else:
            lol2.append(i)
    lol = lol2

print json.dumps(dol, indent=4)

结果:

{
    "a": [
        "a", 
        "x", 
        "b"
    ], 
    "p": [
        "p"
    ], 
    "k": [
        "k", 
        "f"
    ]
}

【讨论】:

    【解决方案2】:

    撇开 e2/e3 不谈,这是一个粗略的草案。

    第一个生成器按值对数据进行分组,但它确实需要按值对数据进行排序。

    然后是一个示例使用,首先是原始数据,然后是按值重新排序的数据。

    In [32]: def cluster(lol, threshold=0.1):
        cl, start = None, None
        for e1, e2, e3 in lol:
            if cl and abs(start - e3) <= threshold:
                cl.append(e1)
            else:
                if cl: yield cl
                cl = [e1]
                start = e3
                 if cl: yield cl
    
    In [33]: list(cluster(lol))
    Out[33]: [['a', 'x'], ['k'], ['p'], ['b'], ['f']]
    
    In [34]: list(cluster(sorted(lol, key = lambda ar:ar[-1])))
    Out[34]: [['x', 'a', 'b'], ['k', 'f'], ['p']]
    

    【讨论】:

      猜你喜欢
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      • 2018-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多