Существует ли эффективная реализация Python для Somers'D для негруппированных переменных? ⇐ Python
-
Anonymous
Существует ли эффективная реализация Python для Somers'D для негруппированных переменных?
Я ищу эффективную реализацию Somers'D на Python, для которой мне нужно вычислить количество согласованных, несогласованных и связанных пар между двумя случайными величинами X и Y. Две пары (X_i, Y_i), (X_j , Y_j) согласованы, если совпадают ранги обоих элементов; то есть x_i > x_j и y_i > y_j или x_i < x_j и y_i < y_j. Две пары называются несогласными, если ранги обоих элементов не совпадают: x_i > x_j и y_i < y_j или x_i < x_j и >y_i > y_j. Говорят, что две пары связаны X (Y), если x_i = x_j y_i = y_j.
D Сомерса затем вычисляется как D = (N_C - N_D) / (N_tot - N_Ty). (См.: https://en.wikipedia.org/wiki/Somers%27_D.)
Я написал простую реализацию, используя вложенные циклы for. Здесь S содержит мои прогнозы, а Y — реализованные результаты.
def concordance_computer(Y, S): Н_К = 0 Н_Д = 0 Н_Т_у = 0 Н_Т_х = 0 для i в диапазоне (0, len(S)): для j в диапазоне (i+1, len(Y)): Y1 = Y[я] X1 = S[я] Y2 = Y[j] X2 = S[j] если Y1 > Y2 и X1 > X2: Н_З += 1 elif Y1 < Y2 и X1 < X2: Н_З += 1 элиф Y1 > Y2 и X1 < X2: Н_Д += 1 элиф Y1 < Y2 и X1 > X2: Н_Д += 1 элиф Y1 == Y2: Н_Т_у += 1 элиф X1 == X2: Н_Т_х += 1 N_tot = len(S)*(len(S)-1)/2 SomersD = (N_C - N_D) / (N_tot - N_T_y) вернуть СомерсД Очевидно, что это будет очень медленно, если (Y,S) содержит много строк. Я наткнулся на использование bisect при поиске решений в сети:
merge['Y'] = Y слияние['S'] = S нули2 = merge.loc[merge['Y'] == 0] ones2 = merge.loc[merge['Y'] == 1] из импорта bisect_bisect_left, bisect_right защита bin_conc(нули2, единицы2): zeros2_list = sorted([zeros2.iloc[j, 1] для j в диапазоне(len(zeros2))]) нули2_длина = len(список зеро2_) конц = диск = связи = 0 для меня в диапазоне (len(ones2)): cur_conc = bisect_left(zeros2_list, ones2.iloc[i, 1]) cur_ties = bisect_right(zeros2_list, ones2.iloc[i, 1]) - cur_conc конц += cur_conc связи += cur_ties диск += нули2_длина - cur_ties - cur_conc пары_tested = длина_нулей2 * len(ones2.index) вернуть концентрацию, диск, ничьи, пары_проверено Это очень эффективно, но работает только для двоичных переменных Y. Теперь мой вопрос: как я могу эффективно реализовать concordance_computer для разгруппированного Y?
Я ищу эффективную реализацию Somers'D на Python, для которой мне нужно вычислить количество согласованных, несогласованных и связанных пар между двумя случайными величинами X и Y. Две пары (X_i, Y_i), (X_j , Y_j) согласованы, если совпадают ранги обоих элементов; то есть x_i > x_j и y_i > y_j или x_i < x_j и y_i < y_j. Две пары называются несогласными, если ранги обоих элементов не совпадают: x_i > x_j и y_i < y_j или x_i < x_j и >y_i > y_j. Говорят, что две пары связаны X (Y), если x_i = x_j y_i = y_j.
D Сомерса затем вычисляется как D = (N_C - N_D) / (N_tot - N_Ty). (См.: https://en.wikipedia.org/wiki/Somers%27_D.)
Я написал простую реализацию, используя вложенные циклы for. Здесь S содержит мои прогнозы, а Y — реализованные результаты.
def concordance_computer(Y, S): Н_К = 0 Н_Д = 0 Н_Т_у = 0 Н_Т_х = 0 для i в диапазоне (0, len(S)): для j в диапазоне (i+1, len(Y)): Y1 = Y[я] X1 = S[я] Y2 = Y[j] X2 = S[j] если Y1 > Y2 и X1 > X2: Н_З += 1 elif Y1 < Y2 и X1 < X2: Н_З += 1 элиф Y1 > Y2 и X1 < X2: Н_Д += 1 элиф Y1 < Y2 и X1 > X2: Н_Д += 1 элиф Y1 == Y2: Н_Т_у += 1 элиф X1 == X2: Н_Т_х += 1 N_tot = len(S)*(len(S)-1)/2 SomersD = (N_C - N_D) / (N_tot - N_T_y) вернуть СомерсД Очевидно, что это будет очень медленно, если (Y,S) содержит много строк. Я наткнулся на использование bisect при поиске решений в сети:
merge['Y'] = Y слияние['S'] = S нули2 = merge.loc[merge['Y'] == 0] ones2 = merge.loc[merge['Y'] == 1] из импорта bisect_bisect_left, bisect_right защита bin_conc(нули2, единицы2): zeros2_list = sorted([zeros2.iloc[j, 1] для j в диапазоне(len(zeros2))]) нули2_длина = len(список зеро2_) конц = диск = связи = 0 для меня в диапазоне (len(ones2)): cur_conc = bisect_left(zeros2_list, ones2.iloc[i, 1]) cur_ties = bisect_right(zeros2_list, ones2.iloc[i, 1]) - cur_conc конц += cur_conc связи += cur_ties диск += нули2_длина - cur_ties - cur_conc пары_tested = длина_нулей2 * len(ones2.index) вернуть концентрацию, диск, ничьи, пары_проверено Это очень эффективно, но работает только для двоичных переменных Y. Теперь мой вопрос: как я могу эффективно реализовать concordance_computer для разгруппированного Y?