Я написал код для теста Уилкоксона со знаком для медианы (статистический непараметрический тест), потому что мне нужно делать это сотни раз.
Тест-статистика вычисляется с использованием следующих шагов:
начать со столбца значений
вычесть постояннуюот каждого значения, чтобы получить столбец различий (с сохранением знака +/-)
теперь удалите все - знаки, чтобы получить только положительные значения (поэтому абсолютные различия)
ранжируйте эти абсолютные различия по порядку величины (от 1 до n)
добавьте ранги, связанные только с положительными различиями на шаге 2, чтобы получить статистику теста, W..
Этот код, кажется, делает то, что мне нужно - для моих образцов данных, который ведет себя хорошо. Тем не менее, я хочу сделать это надежным, потому что у меня есть сотни наборов данных, некоторые из которых, возможно, не так хорошо себя ведут. Два способа, которыми данные могут быть хитрыми (и мой код явно не обрабатывает их):
- Что если два значения идентичны? Мой код явно не касается связей. Связанным значениям следует присвоить средний ранг.
- Что если два (или более) значения равноудалены от константы, но одно больше, а другое меньше? Затем, после удаления знака в AbsDiffs, я не смогу их различить.
Есть предложения?
Вот код:
SetLength(AbsDiffVals, CtrlsList.Count)
for J := 0 to CtrlsList.Count - 1 do
begin
Diff := StrToFloat(CtrlsList[J]) - StrToFloat(HypMed);
DiffVals.Add(FloatToStr(Diff));
AbsDiff := Abs(Diff);
AbsDiffVals[J] := AbsDiff;
end;
`//sort array AbsDiffVals
for J := 0 to Length(AbsDiffVals)-2 do
begin
for K := J+1 to Length(AbsDiffVals)-1 do
begin
if AbsDiffVals[J] < AbsDiffVals[K] then continue
else if AbsDiffVals[J] > AbsDiffVals[K] then
begin
Temp1 := AbsDiffVals[J];
Temp2 := AbsDiffVals[K];
AbsDiffVals[J] := Temp2;
AbsDiffVals[K] := Temp1;
end;
end;
end;`
//put the absolute diffs in a TStringList
for J := 0 to Length(AbsDiffVals)-1 do
begin
AbsDiffValsList.Add(FloatToStr(AbsDiffVals[J]));
end;
//associate the sorted values with the sign of corresponding value in DiffVals
//also assign - sign to rank if sign in DiffVals is -; else + sign
SetLength(RankVals, Length(AbsDiffVals));
for J := 0 to DiffVals.Count - 1 do
begin
Temp := Abs(StrToFloat(DiffVals[J]));
Rank := AbsDiffValsList.IndexOf(FloatToStr(Temp))+1;//Find the rank of the value
if StrToFloat(DiffVals[J]) < 0 then Rank := Rank * -1
else Rank := Rank * 1;
RankVals[J] := Rank;
end;
//replace all negative ranks with 0 and retain all positive ranks
for J := 0 to Length(RankVals) - 1 do
begin
if RankVals[J] < 0 then RankVals[J] := 0
else continue;
end;
//store modified ranks (0 if negative) in TSTringList for easy saving to file
for J := 0 to Length(RankVals) - 1 do
begin
RankList.Add(IntToStr(RankVals[J]));
end;```