我用谷歌搜索过,我已经测试过了,这让我知道了。我有一个我需要按相似性分组的数字列表。例如,在[1,6,9,10,110,105,109,134,139]的列表中,1 6 9将被放入列表中,100,102,105和109将被放入一个列表中。列表,134和139.我在数学方面很糟糕,我已经尝试过尝试过,但我无法让它发挥作用。为了尽可能明确,我希望将10个值之间的数字组合在一起。有人可以帮忙吗?感谢。
答案 0 :(得分:27)
有许多方法可以cluster analysis。一种简单的方法是查看连续数据元素之间的间隙大小:
def cluster(data, maxgap):
'''Arrange data into groups where successive elements
differ by no more than *maxgap*
>>> cluster([1, 6, 9, 100, 102, 105, 109, 134, 139], maxgap=10)
[[1, 6, 9], [100, 102, 105, 109], [134, 139]]
>>> cluster([1, 6, 9, 99, 100, 102, 105, 134, 139, 141], maxgap=10)
[[1, 6, 9], [99, 100, 102, 105], [134, 139, 141]]
'''
data.sort()
groups = [[data[0]]]
for x in data[1:]:
if abs(x - groups[-1][-1]) <= maxgap:
groups[-1].append(x)
else:
groups.append([x])
return groups
if __name__ == '__main__':
import doctest
print(doctest.testmod())
答案 1 :(得分:6)
这将找到群组:
nums = [1, 6, 9, 100, 102, 105, 109, 134, 139]
for k, g in itertools.groupby(nums, key=lambda n: n//10):
print k, list(g)
0 [1, 6, 9]
10 [100, 102, 105, 109]
13 [134, 139]
请注意,如果nums实际上没有按照您的示例显示进行排序,则需要先对其进行排序。
答案 2 :(得分:2)
首先,您可以轻松地将任何序列转换为一系列相邻项目。只需开球,将它向前移动,然后拉上未移位和不移位的副本。唯一的诀窍是你需要从(<something>, 1)
或(139, <something>)
开始,因为在这种情况下我们不需要每对元素,而是每个元素都有一对:
def pairify(it):
it0, it1 = itertools.tee(it, 2)
first = next(it0)
return zip(itertools.chain([first, first], it0), it1)
(这不是编写它的最简单方法,但我认为对于那些不熟悉itertools
的人来说,这可能是最具可读性的方式。)< / p>
>>> a = [1, 6, 9, 100, 102, 105, 109, 134, 139]
>>> list(pairify(a))
[(1, 1), (1, 6), (6, 9), (9, 100), (100, 102), (102, 105), (105, 109), (109, 134), (134, 139)]
然后,使用稍微复杂一点的Ned Batchelder键,你可以使用groupby
。
但是,我认为在这种情况下,这最终会比执行相同操作的显式生成器更复杂。
def cluster(sequence, maxgap):
batch = []
for prev, val in pairify(sequence):
if val - prev >= maxgap:
yield batch
batch = []
else:
batch.append(val)
if batch:
yield batch