Слияние бин-данные через бин пороговое количество


При выполнении теста хи-квадрат, один квадрат разности ожидаемых отсчетов в bin и наблюдение за подсчетом голосов в мусорное ведро, и делит эти ТВ-ОГРН различий на счету в мусорное ведро, как это видно из Формулы ниже.

enter image description here

Однако, я слышал, что это хорошая практика, чтобы изменить закрома такие, что наблюдаемые показатели выше порогового (обычно 5, иногда меньше), так как большое количество Бен считает ниже такого порога может привести к плохой подгонки (при условии, сведены к минимуму хи-квадрат). Если наблюдаемый граф ОГРН меньше этого порога, то Бен объединяется с рядом. Если предположить, что распределение (например, Гаусса) с центральным пиком, это будет следующим-справа бин (I до I+1 ящик) когда ящики слева от центрального пика в то время как рядом будет следующий-левый бункер (I до I-1 ведро), когда ящики находятся справа от центрального пика.

Я создал алгоритм, который я считаю работает и покрывает все-крайние случаи (если один центральный пик). Мне было интересно, как это может быть улучшено с точки зрения скорость/эффективность. Я также чувствую, что я дублировать код, используя аналогичные подходы в двух циклов while; это может быть предотвращено?

import numpy as np

## CONVENIENCE FUNCTIONS
get_midpoints = lambda edges : (edges[1:] + edges[:-1])/2
verify = lambda string, data : print("\n .. {} {}:\n{}\n".format(len(data), string, data))

## SAMPLE DATA
bin_edges = np.linspace(0, 40, 9)
bin_mids = get_midpoints(bin_edges)
bin_counts = np.array([2, 12, 21, 31, 18, 9, 3, 1])

## DESIRED OUTPUT (VIA THRESHOLD=5)
upd_edges = np.array([0, 10, 15, 20, 25, 40])
upd_mids = get_midpoints(upd_edges)
upd_counts = np.array([14, 21, 31, 18, 13])

## ALGORITHM TO MODIFY BINS
def modify_bins(edges, counts, threshold=None):
    """
    This function returns the bin edges, bin midpoints, and bin counts
    with the option of including a count threshold.

    edges       :   type <array>
    counts      :   type <array>
    threshold   :   type <int> greater than 0 or None
    """
    if threshold is None:
        return edges, mids, counts
    else:
        ## INITIALIZE
        loc_peak = np.argmax(counts)
        left_edges = [edges[0]]
        left_counts = []
        right_edges = []
        right_counts = []

        ## CONSOLIDATE BINS LEFT OF PEAK
        idx = 0
        while idx <= loc_peak:
            count_tmp = counts[idx]
            edge_tmp = edges[idx+1]
            while count_tmp < threshold:
                idx += 1
                count_tmp += counts[idx]
                edge_tmp = edges[idx+1]
            left_edges.append(edge_tmp)
            left_counts.append(count_tmp)
            idx += 1

        ## CONSOLIDATE BINS RIGHT OF PEAK
        idx = len(counts) - 1
        while idx > loc_peak:
            count_tmp = counts[idx]
            edge_tmp = edges[idx+1]
            while count_tmp < threshold:
                idx -= 1
                count_tmp += counts[idx]
                edge_tmp = edges[idx+1]
            right_edges.append(edge_tmp)
            right_counts.append(count_tmp)
            idx -= 1

        ## GROUP LEFT & RIGHT DATA
        right_edges[0] = edges[-1]
        mod_edges = np.array(left_edges + right_edges[::-1])
        mod_counts = np.array(left_counts + right_counts[::-1])
        mod_mids = get_midpoints(mod_edges)
        return mod_edges, mod_mids, mod_counts

# mod_edges, mod_mids, mod_counts = modify_bins(bin_edges, bin_counts, threshold=None)
mod_edges, mod_mids, mod_counts = modify_bins(bin_edges, bin_counts, threshold=5)

## VERIFY
verify("ORIGINAL EDGES", bin_edges)
verify("ORIGINAL MIDPOINTS", bin_mids)
verify("ORIGINAL COUNTS", bin_counts)
print("-----------------------------")
verify("DESIRED EDGES", upd_edges)
verify("DESIRED MIDPOINTS", upd_mids)
verify("DESIRED COUNTS", upd_counts)
print("-----------------------------")
verify("MODIFIED EDGES", mod_edges)
verify("MODIFIED MIDPOINTS", mod_mids)
verify("MODIFIED COUNTS", mod_counts)


Комментарии