2014-11-13 3 views
0

У меня есть список значений, описывающих некоторую совокупность. Значения распределяются на два пика, как показано на приведенной ниже гистограмме. histogram with two distinct peaksРазделить популяцию на два в Python

Есть ли простой способ автоматического обнаружения «зазора» в центре распределения и разбиения исходного списка на две стороны? Идеально использовать numpy, если это возможно.

Редактировать добавить: Очевидно, я мог бы просто отсортировать список, перебрать его и разбить на первое нулевое значение, но Я надеюсь, что существует более надежный метод, который является «разумным», даже если оба пика не так четко разделены. Обратите внимание, что комментарий strikethro не работает, это гистограмма, которая имеет нулевые значения, а не данные, oops!

+0

только один раскол? что, если есть еще один образец, например:: 0,4 –

+0

Ну, только наличие 2 подгрупп было частью первоначального предположения, но вы заставили меня расспросить его по моему конкретному случаю! – lost

ответ

1

Если информация о вашем распределении содержит априорную информацию, например: есть только две группы, которые являются группами в группах. Затем вы можете использовать наивный алгоритм: найти больший разрыв между двумя образцами.

Но проблема spliting популяции на подмножества (кластеры) нетривиален, и обычно решается с помощью алгоритмов кластеризации машинного обучения: ответ http://scikit-learn.org/stable/modules/clustering.html

+0

Спасибо. Я соглашусь на это, поскольку на самом деле он точно отвечает на исходный вопрос, но предлагает более гибкий подход в качестве дополнительного ответа. – lost

0

Жан-Лу хорошо работает на вопрос, поставленный. Однако, имея рабочую, простую реализацию, мне удалось немного подумать о проблеме, и я публикую подход, который я придумал, и в случае, если это полезно.

def split_population2(seq, n_bins): 
    """ Split a population into sub-populations 

     Based on binning the data into n_bins and finding contigous groups of non-empty bins. 

     Returns [lowest, ..., highest] all of which are sorted sequences 
    """ 
    sorted_pop = sorted(seq) 

    # bin the data into n_bins in a 2d structure, one sequence for each bin: 
    _ , bins = np.histogram(sorted_pop, bins=n_bins) 
    bin_indices = np.digitize(sorted_pop, bins) 
    binned = [] 
    for i in range(len(bins)+1): 
     binned.append([]) 
    for ix_bin, v in zip(bin_indices, sorted_pop): 
     binned[ix_bin].append(v) 

    # now join-up non-empty bins 
    joined_bins = [[]] # so 2D, with initially 1 sub-list 
    len_last_bin = 0 
    for bin in binned: 
     len_bin = len(bin) 
     if len_bin == 0 and len_last_bin != 0: # will correctly handle the case where bin 0 is empty 
      joined_bins.append([]) 
     if len_bin != 0: 
      joined_bins[-1].extend(bin) 
     len_last_bin = len_bin 

    return joined_bins 

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

original histogram histogram showing sub-populations

Смежные вопросы