def evaluate_pairwise_metrics(contingency_table: np.ndarray, N: int, evaluation: Evaluation, is_sampled_graph: bool = False): """Evaluates the pairwise metrics for goodness of the partitioning. Metrics evaluated: rand index, adjusted rand index, pairwise recall, pairwise precision. Parameters --------- contingency_table : np.ndarray (int) the contingency table (confusion matrix) comparing the true block assignment to the algorithmically determined block assignment N : int the number of nodes in the confusion matrix evaluation : Evaluation stores evaluation results is_sampled_graph : bool True if evaluation is for a sampled graph. Default = False """ # Compute pair-counting-based metrics def nchoose2(a): return misc.comb(a, 2) num_pairs = nchoose2(N) colsum = np.sum(contingency_table, axis=0) rowsum = np.sum(contingency_table, axis=1) # compute counts of agreements and disagreement (4 types) and the regular rand index count_in_each_b1 = np.sum(contingency_table, axis=1) count_in_each_b2 = np.sum(contingency_table, axis=0) num_same_in_b1 = sum(count_in_each_b1 * (count_in_each_b1 - 1)) / 2 num_same_in_b2 = sum(count_in_each_b2 * (count_in_each_b2 - 1)) / 2 num_agreement_same = 0.5 * sum( sum(contingency_table * (contingency_table - 1))) num_agreement_diff = calc_num_agreement_diff(contingency_table, N, colsum, rowsum) num_agreement = num_agreement_same + num_agreement_diff rand_index = num_agreement / num_pairs adjusted_rand_index = calc_adjusted_rand_index(contingency_table, nchoose2, colsum, rowsum, num_pairs) if is_sampled_graph: evaluation.sampled_graph_rand_index = rand_index evaluation.sampled_graph_adjusted_rand_index = adjusted_rand_index evaluation.sampled_graph_pairwise_recall = num_agreement_same / num_same_in_b1 evaluation.sampled_graph_pairwise_precision = num_agreement_same / num_same_in_b2 else: evaluation.rand_index = rand_index evaluation.adjusted_rand_index = adjusted_rand_index evaluation.pairwise_recall = num_agreement_same / num_same_in_b1 evaluation.pairwise_precision = num_agreement_same / num_same_in_b2 print('Rand Index: {}'.format(rand_index)) print('Adjusted Rand Index: {}'.format(adjusted_rand_index)) print('Pairwise Recall: {}'.format(num_agreement_same / (num_same_in_b1))) print('Pairwise Precision: {}'.format(num_agreement_same / (num_same_in_b2))) print('\n')