#arrays #excel #vba #function
#массивы #excel #vba #функция
Вопрос:
Давайте определим большие выбросы как наблюдения, которые соответствуют неравенству :
И небольшие выбросы в качестве наблюдений, которые соответствуют неравенству :
Я хочу написать функцию replace_outliers(table, std)
, которая будет проходить через все переменные (все столбцы) и заменит большие выбросы на верхнюю границу, т.е.
и небольшие выбросы с нижней границей, т.е.
Моя работа до сих пор
Что я сделал, так это написал функцию для одномерной ситуации (работает только тогда, когда у меня есть только один столбец).
Function replace_outliers(table As Range, std As Double)
Dim temp() As Variant
temp = table.Value
Dim mean As Double
mean = Application.WorksheetFunction.Average(temp)
Dim stdv As Double
stdv = Application.WorksheetFunction.StDev(temp)
Dim upper_bound As Double
Dim lower_bound As Double
upper_bound = std * stdv mean
lower_bound = mean - stdv * std
Dim i As Long
For i = 1 To UBound(temp, 1)
If (temp(i, 1) - mean) / stdv > std Then
temp(i, 1) = upper_bound
ElseIf (temp(i, 1) - mean) / stdv < -std Then
temp(i, 1) = lower_bound
End If
Next
replace_outliers = temp
End Function
Пример :
Однако я не уверен, что мне следует сделать, чтобы расширить это для многовариантной ситуации (т. Е. Применить replace_outliers(table, std)
для каждого столбца в предоставленной таблице ввода. Есть ли у вас какие — нибудь идеи , как это можно выполнить ?
Редактировать
Я попытался перебрать ее по столбцам. Это моя работа :
Function outliers_std_1(table As Range, std As Double)
Dim temp() As Variant
temp = table.Value
Dim j As Long
For j = 1 To UBound(temp, 2)
Dim mean As Double
mean = Application.WorksheetFunction.Average(table.Columns(j))
Dim stdv As Double
stdv = Application.WorksheetFunction.StDev(table.Columns(j))
Dim upper_bound As Double
Dim lower_bound As Double
upper_bound = std * stdv mean
lower_bound = mean - stdv * std
Dim i As Long
For i = 1 To UBound(temp, j)
If (temp(i, j) - mean) / stdv > std Then
temp(i, j) = upper_bound
ElseIf (temp(i, j) - mean) / stdv < -std Then
temp(i, j) = lower_bound
End If
Next
Next
outliers_std_1 = temp
End Function
Однако я получаю #ARG
! ошибка при попытке запустить ее с данными ниже :
Комментарии:
1.
temp
это 2D-массив, поэтому вы можете легко добавить внутренний (или, возможно, внешний) цикл по столбцам вместо жестко запрограммированного1
. См. Раздел Массивы и диапазоны .2. Внутренний цикл:
Dim j as Long
аFor j = 1 to Ubound(temp,2)
затем замените всеtemp(i,1)
наtemp(i,j)
3. Хм, я пытался использовать ваши советы, чтобы зациклить его после столбца, но мне не удалось сделать это правильно. Я обновил свой вопрос. Я что-то пропустил?
4.
mean = Application.WorksheetFunction.Average(table.Columns(j))
и т. д5. Хммм, я скорректировал свой код со средним значением вычисления и стандартным отклонением, но я все еще вижу #ARG!. Пожалуйста, взгляните на мой код
Ответ №1:
Проверено:
Function outliers_std_1(table As Range, std As Double)
Dim temp As Variant, j As Long, i As Long
Dim mean As Double, stdv As Double
Dim upper_bound As Double
Dim lower_bound As Double
temp = table.Value
For j = 1 To UBound(temp, 2)
mean = Application.WorksheetFunction.Average(table.Columns(j))
stdv = Application.WorksheetFunction.StDev(table.Columns(j))
upper_bound = mean (std * stdv)
lower_bound = mean - (stdv * std)
For i = 1 To UBound(temp, 1)
If temp(i, j) < lower_bound Then
temp(i, j) = lower_bound
ElseIf temp(i, j) > upper_bound Then
temp(i, j) = upper_bound
End If
Next
Next
outliers_std_1 = temp
End Function