Поиск всех возможных комбинаций корзин

У меня есть 100 000 наблюдений с переменной age в диапазоне 18-80. Я хочу найти X корзины на основе переменной age. Диапазоны бинов не должны перекрываться и вместе должны охватывать весь интервал. Например, с X = 4 возможной комбинацией корзин может быть:

  • 18-30
  • 31-45
  • 46-57
  • 58-80

Как мне найти все возможные комбинации бинов, учитывая значение X?

Редактировать: По подсказке @Wolf, вот еще одно ограничение, которое я хотел реализовать сам. Каждый бин должен содержать не менее 10 значений переменной age. Это, конечно, ограничивает X, так что X <= 6.

Я пытался интегрировать это в ответ @mkrieger1, но потерпел неудачу.

def bin_combinations(values, n):
    """
    Generate all possible combinations of splitting the values into n
    contiguous parts.

    >>> list(bin_combinations('abcd', 3))
    [['a', 'b', 'cd'], ['a', 'bc', 'd'], ['ab', 'c', 'd']]
    """

    for indices in combinations(range(1, len(values)), n - 1):
        li = list(indices)
        starts = [None] + li
        ends = li + [None]
        size = li[-1] - li[0]
        if size >= 10:
            yield [values[start:end] for start, end in zip(starts, ends)]

person pir    schedule 02.07.2015    source источник
comment
Есть ли какие-либо дополнительные ограничения для этих контейнеров? Например, будет ли 18, 19, 20, 21-80 допустимой комбинацией?   -  person Wolf    schedule 02.07.2015
comment
Я обновил свой пост.   -  person pir    schedule 02.07.2015
comment
Вы пытались адаптировать мое решение к вашей проблеме с ограничениями?   -  person mkrieger1    schedule 02.07.2015
comment
Да, но мне трудно выбрасывать целый набор мусорных ведер вместо одного. См. код ниже: for indices in combinations(range(1, len(values)), n - 1): li = list(indices) starts = [None] + li ends = li + [None] size = li[-1] - li[0] if size >= 10: yield [values[start:end] for start, end in zip(starts, ends)]   -  person pir    schedule 02.07.2015
comment
Я пробовал несколько различных изменений, но не повезло.   -  person pir    schedule 02.07.2015
comment
Как насчет включения в вопрос того, что вы уже пробовали? Это будет более читаемо, чем в комментарии, и абсолютно соответствует SO ;-)   -  person Wolf    schedule 02.07.2015
comment
Хорошо, это хорошо знать. Я включил это в вопрос :)   -  person pir    schedule 05.07.2015


Ответы (1)


Наиболее целесообразно находить комбинации с помощью функции combinations из itertools модуль стандартной библиотеки.

from itertools import combinations

def bin_combinations(values, n):
    """
    Generate all possible combinations of splitting the values into n
    contiguous parts.

    >>> list(bin_combinations('abcd', 3))
    [['a', 'b', 'cd'], ['a', 'bc', 'd'], ['ab', 'c', 'd']]
    """
    for indices in combinations(range(1, len(values)), n - 1):
        starts = [None] + list(indices)
        ends = list(indices) + [None]
        yield [values[start:end] for start, end in zip(starts, ends)]
person mkrieger1    schedule 02.07.2015
comment
Спасибо за быстрый ответ! Я добавил еще одно ограничение (см. мой пост). - person pir; 02.07.2015