在Python中使用数字之间的相对关系对数字进行分组/聚类

2024-10-02 02:31:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要类似的东西,而不是问here,但更反过来:

给出一个数字列表(上面问题的例子):[1,6,9,100,102,105,109,134,139]我不想说最大差距(在这个例子中是10),但我想说多少组

例如。 3组:1、6、9/100、102、105、109/134、139 2组:1、6、9/100、102、105、109、134、139 ...

这应该是相对的,因为我的数字非常非常不同: [0.1、0.2、1、4、100、110]=>; 3组应引出0.1、0.2/1、4/100、110

尽管0.2和1在绝对值上比1和5更接近(0.8对3),但相对而言,0.2离1(5倍)比离0.1(2倍)更远

我希望能弄清楚我想实现什么


Tags: gt列表here数字例子差距比离
2条回答
import sys

# Sorted numbers.
xs = [0.1, 0.2, 1, 4, 100, 110]
xs.sort()

# Reverse-sorted (RATIO, INDEX) tuples.
tups = sorted(
    (
        (xs[i] / xs[i - 1] if i else 0, i)
        for i, x in enumerate(xs)
    ),
    reverse = True,
)

# Indexes of the boundaries having the largest ratios.
n_groups = int(sys.argv[1])
boundaries = sorted(tup[1] for tup in tups[0 : n_groups - 1])
boundaries.append(None)

# Create the groups, based on those boundaries.
groups = []
i = 0
for j in boundaries:
    groups.append(xs[i:j])
    i = j

# Check.
for g in groups:
    print(g)

输出示例:

# n_groups = 1
[0.1, 0.2, 1, 4, 100, 110]

# n_groups = 2
[0.1, 0.2, 1, 4]
[100, 110]

# n_groups = 3
[0.1, 0.2]
[1, 4]
[100, 110]

# n_groups = 4
[0.1, 0.2]
[1]
[4]
[100, 110]

# n_groups = 5
[0.1]
[0.2]
[1]
[4]
[100, 110]

如果数字列表不是巨大的,我会首先计算一个数字和它的前例之间的每一个比率,然后选择最大的分割

例如:

def split_numbers_list(numbers_list, n_groups):
    # If the number of groups is 1 or less, the whole list the only group
    if n_groups <= 1:
        return [numbers_list]
    n_splits = min(len(numbers_list), n_groups) # Can't have more groups than elements
    # Now we calculate the ratios and store them in (index, ratio) tuples
    ratios = [
        (i, numbers_list[i + 1] / numbers_list[i]) for i in range(len(numbers_list) - 1)
    ]
    sorted_ratios = sorted(ratios, key=lambda r: r[1], reverse=True)
    # `chosen_splits` stores the boundaries of each group
    chosen_splits = (
        [0]
        + sorted([r[0] + 1 for r in sorted_ratios[: n_splits - 1]])
        + [len(numbers_list)]
    )
    return [
        numbers_list[chosen_splits[i] : chosen_splits[i + 1]]
        for i in range(len(chosen_splits) - 1)
    ]

但是请注意这对numbers_list的假设:它必须是一个排序的严格正的数字列表,否则这个函数将不起作用

一些例子:

>>> my_list = [1, 2, 3, 4, 5, 100, 101, 103, 504, 2301]

>>> split_numbers_list(my_list, 5)
[[1], [2, 3, 4, 5], [100, 101, 103], [504], [2301]]

>>> split_numbers_list(my_list, 3)
[[1, 2, 3, 4, 5], [100, 101, 103], [504, 2301]]

相关问题 更多 >

    热门问题