Функция для группировки номеров одинакового диапазона вместе? - PullRequest
0 голосов
/ 01 апреля 2019

У меня есть список чисел, которые я хочу разделить на разные группы в зависимости от того, насколько они близки друг с другом

List1=[1.8, 1.1, 1.9, 11, 9, 10, 36, 39, 44, 20]

Когда я смотрю на этот список, я сразу же узнаю, что есть 4 группы чиселпервые 3 попадают в одну группу, следующие 3 попадают в одну группу, следующие 3 попадают в одну группу, а последнее число (20) входит в собственную группу.Я не совсем уверен, как я это делаю, но я думаю, что другие люди, вероятно, согласятся со мной

Что я делаю в своей голове, чтобы определить это?Есть ли функция, чтобы сделать это в Python?

Ответы [ 2 ]

0 голосов
/ 01 апреля 2019

Данные вашего примера и интуиция соответствуют следующему правилу: «Два значения находятся в одной группе, если расстояние между ними не превышает 1 стандартного отклонения, удаленного из средних расстояний между значениями во всей группе».

Вот код, который говорит то же самое:

from statistics import stdev

# sort the data, for simplicity
data = sorted([1.8, 1.1, 1.9, 11, 9, 10, 36, 39, 44, 20])

# create a list of the gaps between the consecutive values
gaps = [y - x for x, y in zip(data[:-1], data[1:])]
# have python calculate the standard deviation for the gaps
sd = stdev(gaps)

# create a list of lists, put the first value of the source data in the first
lists = [[data[0]]]
for x in data[1:]:
    # if the gap from the current item to the previous is more than 1 SD
    # Note: the previous item is the last item in the last list
    # Note: the '> 1' is the part you'd modify to make it stricter or more relaxed
    if (x - lists[-1][-1]) / sd > 1:
        # then start a new list
        lists.append([])
    # add the current item to the last list in the list
    lists[-1].append(x)

print(lists)

Вывод:

[[1.1, 1.8, 1.9], [9, 10, 11], [20], [36, 39, 44]]

Я предполагаю, что порядок сортировки не имеет значения.

Чтобы ответить на мой собственный вопрос в комментариях, если вы добавите 15 и 25, результат будет следующим:

[[1.1, 1.8, 1.9], [9, 10, 11], [15], [20], [25], [36, 39], [44]]

Обратите внимание, что после добавления 15 и 25 стандартное отклонение изменилось, поэтому 44 было отделенов своей собственной маленькой группе.Если к этому добавить 17, оно становится:

[[1.1, 1.8, 1.9], [9, 10, 11], [15, 17, 20], [25], [36, 39], [44]]

Или, если вы не добавите 17, а вместо этого потребуете, чтобы расстояние не превышало 1,6 SD:

[[1.1, 1.8, 1.9], [9, 10, 11, 15, 20, 25], [36, 39, 44]] 
0 голосов
/ 01 апреля 2019

Очень грязно и долго в данный момент, но я верю, что это выполняет то, что вы хотели:

def define_groups(l, threshold = .4):
    groups = {}
    its = 0
    for i in l:
        numbers_except = list(l)
        del numbers_except[(l.index(i))]
        for x in range(len(numbers_except)):
            if percentage_diff(i, numbers_except[x]) < threshold:
                try:
                    groups[its].append(numbers_except[x])
                except:
                    groups[its] = [numbers_except[x]]
                del l[l.index(numbers_except[x])]
        try:
            groups[its].append(i)
        except:
            groups[its] = [i]
        its += 1
    print(groups)

def percentage_diff(a, b):
    return abs(abs(a-b)) / max([a,b])

In [0]: define_groups([1.8, 1.1, 1.9, 11, 9, 10, 36, 39, 44, 20]) {0: [1.1, 1.9, 1.8], 1: [9, 10, 11], 2: [39, 44, 36], 3: [20]}

Пороговая величина может быть очень легко изменена, чтобы включать только изменение в значении, но тогда она будет непропорциональна от более низких чисел к более высоким значениям, и это создаст группы, которые не соответствуют описанному вами. Вот почему я использовал проверку процентного изменения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...