В настоящее время это почти идеальное решение. Проблема в том, что когда вы хотите рассчитать среднее значение для нескольких совпадений (скажем, все три числа в строке близки к порогу), вы должны принять правильное количество значений при вычислении среднего значения. Это легко, если есть только 1 или 3 матча из 3 столбцов. Но когда две пары чисел «близки», а третья - нет, код ниже будет иметь ошибку.
Идея заключается в суммировании совпадающих значений для каждой строки и каждой комбинации. Если только, скажем, строки 'A'
и 'B'
являются «близкими» (в пределах порога), мы получаем df.A+df.B
, который необходимо разделить на 2, чтобы получить среднее значение. Когда все три «близки», мы получаем 2*df.A + 2*df.B + 2*df.C
, которые можно разделить на 6, чтобы получить среднее значение. Однако в третьем случае мы получаем, например, df.A + 2*df.B + df.C
(когда A и B близки, B и C близки, но A и C не являются). В этом случае мы не можем делить что-либо, чтобы получить надлежащее среднее значение. Вероятно, мы должны разделить на 4, чтобы получить ошибочное значение «примерно одного» элемента. Я хочу сказать, что код был бы намного сложнее, если бы мы правильно относились к этому делу и, в зависимости от ваших потребностей, это не стоило того. Также неясно, как именно вы хотите справиться с этим делом. Текущая версия деления выше на 4 эквивалентна усреднению A vs B, усреднению B против C, а затем усреднению этих средних значений снова.
Так вот:
import numpy as np
import pandas as pd
from itertools import combinations
colnames = ['A', 'B', 'C']
df = pd.DataFrame(np.random.randn(12, 3), columns=colnames)
thresh = .3
df['matches'] = sum(abs(df[k1]-df[k2])<thresh
for k1,k2 in combinations(colnames,2))
# this is your starting point, we'll need df['matches'] too
tmpsums = sum(np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0)
for k1,k2 in combinations(colnames,2))
# divide by 2/4/6:
df['matches_mean'] = np.where(df['matches'],tmpsums/df['matches']/2,0)
Возникающая сумма по выражению генератора достигает границы хорошего вкуса, я признаю. Возможно, вы захотите записать его в правильном цикле, но тогда вам придется постепенно суммировать значения в tmpsums
. Я признаю, что это может быть красивее.
В любом случае, это второе выражение генератора работает аналогично первому. Дали значение, конечно, разные,
np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0)
То есть, это даст нам сумму элементов для данной пары столбца, если эти значения находятся ближе, чем молоти, иначе мы получим 0. Для всех 3 мы получаем массив с такими значениями нуля или суммы двух элементов, и суммируем их снова. Там, где было 0 совпадений, мы получаем 0. Если было 1 совпадение, мы суммируем два совпадающих элемента.В течение двух матчей мы получаем смешанную сумму, о которой я упоминал ранее, и у нас есть все условия дважды в случае 3 матчей.
Осталось разделить ненулевые случаи на число совпадений, что является просто делением с удвоенным количеством совпадений, которое мы уже знаем (но мы должны следить за делением на ноль).
Пример вывода с thresh = 0.3
:
A B C matches matches_mean
0 0.716278 0.681279 0.861410 3 0.752989
1 -0.109029 -0.646952 0.268038 0 0.000000
2 -1.095221 -1.088397 1.100645 1 -1.091809
3 -1.970372 -0.367096 -0.337098 1 -0.352097
4 -1.030003 0.082001 -0.807431 1 -0.918717
5 1.660611 -0.046429 0.557107 0 0.000000
6 -0.508715 -0.588217 0.014917 1 -0.548466
7 0.578028 -0.187097 -0.420243 1 -0.303670
8 0.233687 1.311917 1.888947 0 0.000000
9 0.478863 1.087957 -0.897025 0 0.000000
10 -0.001462 0.866320 -1.198642 0 0.000000
11 0.297946 0.564325 -1.098887 1 0.431135
Что делать, если более чем одна пара колонок близки? Что должно содержать этот столбец? –
Привет Андраш. В конечном итоге я ищу большинство матчей и среднее значение этой группы матчей. Поэтому, если 3 столбца совпадают и 2 совпадают с одной и той же строкой, то среднее из 3 столбцов будет идеальным. Спасибо за любую помощь! – ade1e
А как насчет строк, где нет совпадений? –