Вопрос или проблема
Это почти наверняка человеческие ошибки, но я не могу понять, что я делаю не так. Буду признателен за любые мысли.
Воспроизводимый пример:
data <- structure(list(pre_IB1 = c(-3L, -2L, 2L, 2L), pre_IB2 = c(3L,
-1L, 1L, -3L), pre_IB3 = c(3L, 0L, 0L, -2L), pre_IB4 = c(-3L,
-1L, -1L, -3L), pre_IB5 = c(3L, 0L, -3L, 2L), pre_IH1 = c(3L,
1L, 2L, -3L), pre_IH2 = c(3L, 2L, -3L, -3L), pre_IH3 = c(3L,
1L, 2L, 2L), pre_IH4 = c(3L, 2L, 1L, -3L), foot = c(3L, 3L, 3L,
3L), switch = c(3L, 3L, 3L, 3L), condition = c("ff", "ff", "ff",
"ff"), post_IB1 = c(3L, -2L, 0L, 0L), post_IB2 = c(3L, 0L, -1L,
-1L), post_IB3 = c(3L, 1L, -1L, -1L), post_IB4 = c(3L, -1L, 0L,
-2L), post_IB5 = c(3L, -3L, -3L, 2L), post_IH1 = c(3L, 1L, 1L,
-1L), post_IH2 = c(3L, 1L, -3L, -1L), post_IH3 = c(3L, 1L, 2L,
1L), post_IH4 = c(3L, 2L, 2L, -1L), pol_gen = c(0L, 0L, -1L,
-1L), age = c(76L, 34L, 66L, 35L), gender = c(1L, 1L, 2L, 2L),
trolley = c(2L, 1L, 1L, 1L), participant = c("5c58244f62290e00012fa64c",
"5f50db296d9ce726e639d020", "5d48673efef71c0016d8bf40", "61017941304cf7ac38c2e110"
)), row.names = c(NA, 4L), class = "data.frame")
Я пытаюсь выполнить два расчета, первый простой, второй более сложный. В первом случае я пересчитываю значения ответов, а затем вычисляю средний балл:
data[,1:9] <- apply(data[,1:9], 2, likert_convert,
top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
data[,13:21] <- apply(data[,13:21], 2, likert_convert,
top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
data <- mutate(data, post_consTotal=(post_IB1 + post_IB2 + post_IB3 + post_IB4 + post_IB5 + post_IH1 + post_IH2 + post_IH3 + post_IH4)/9)
Этот код создает значения post_consTotal, которые неверны. Например, во второй строке должно быть (-.66 + 0 + .33 + -.33 + -1 + .33 + .33 + .33 + .66)/9= -0.1, но R выдает -4.934325e-17.
Интересно, что эта проблема не возникает, если я пропускаю шаг пересчета.
Второй расчет, который я выполняю, включает в себя получение чего-то похожего (но не совсем) на среднее абсолютное отклонение между набором переменных. Сначала я пересчитываю, как указано выше, чтобы переменные находились между 1 и -1:
data[,1:9] <- apply(data[,1:9], 2, likert_convert,
top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
data[,13:21] <- apply(data[,13:21], 2, likert_convert,
top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
arrayData = array(data = NA, dim = c(5, 5, nrow(data)))
finalMeanScore = c()
for( numberOfParticipants in 1:nrow(data) ){
tempData = unlist(as.vector(data[ numberOfParticipants, c("pre_IB1", "pre_IB2", "pre_IB3", "pre_IB4", "pre_IB5") ]))
for ( i in 1:length(tempData)){
tempCoh = 1 - abs(tempData[i] - tempData)
arrayData[i,, numberOfParticipants] = tempCoh
}
diag(arrayData[,, numberOfParticipants]) = 0
finalMeanScore[numberOfParticipants] = (sum(arrayData[,, numberOfParticipants]))/20
}
data <- data %>%
mutate(pre_cohIB=finalMeanScore)
Учитывая, что все входные значения находятся между 1 и -1, максимальное абсолютное отклонение составляет 2. Таким образом, строка
tempCoh = 1 - abs(tempData[i] - tempData)
не должна давать отрицательных значений, однако такая ситуация происходит довольно часто.
Я предположил, что это может быть связано с точностью представления чисел с плавающей запятой, что может объяснить первую проблему. Однако расхождение между -0.01 и -0.00000000000000004934325 кажется слишком большим, чтобы его можно было объяснить ошибкой округления.
Извините за длинный и насыщенный пост, любые предложения будут весьма полезны.
Ответ или решение
Ваш вопрос об ошибках вычислений в R действительно интересен и требует внимательного подхода. Давайте разберем обе части вашего кода и возможные причины возникновения ошибок.
1. Ошибка при вычислении post_consTotal
Ваша проблема с вычислением post_consTotal
может быть связана с тем, как именно происходит преобразование значений с помощью функции likert_convert
. Вы указали, что после этого преобразования полученные значения приводят к неожиданным результатам, таким как -4.934325e-17
, когда вы ожидаете, что результат должен быть -0.1
. Это значение близко к нулю и может быть следствием ошибок округления или, возможно, особенностей реализации функции likert_convert
.
Рекомендации по устранению ошибок:
- Убедитесь, что функция
likert_convert
действительно работает корректно и возвращает ожидаемые значения. Возможно, имеет смысл добавить временный вывод для проверки промежуточных значений. - Проверьте, не появляются ли в результатах выполнения функции
NA
или другие недопустимые значения, которые могут повлиять на вычисление суммы/среднего.
Если вам нужно больше контроля над значениями, вы можете временно сохранять промежуточные результаты в отдельные переменные для более легкой отладки:
rescaled_data_pre <- apply(data[,1:9], 2, likert_convert, top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
rescaled_data_post <- apply(data[,13:21], 2, likert_convert, top.x = 3, bot.x = -3, top.y = 1, bot.y = -1)
data[,1:9] <- rescaled_data_pre
data[,13:21] <- rescaled_data_post
# Вычисление post_consTotal
data <- mutate(data, post_consTotal = (post_IB1 + post_IB2 + post_IB3 + post_IB4 + post_IB5 + post_IH1 + post_IH2 + post_IH3 + post_IH4) / 9)
2. Ошибка при вычислении pre_cohIB
Что касается второго расчета и возникновения отрицательных значений в результате выполнения строки tempCoh = 1 - abs(tempData[i] - tempData)
, даже в случае, если все значения находятся в диапазоне от -1 до 1, нет гарантии, что 1 - |x - y|
будет всегда положительным.
Давайте уточним этот момент. Если x
и y
находятся, например, на границе диапазона (-1, 1), то:
- Если
x = 1
иy = -1
, тоtempCoh = 1 - abs(1 - (-1)) = 1 - 2 = -1
, что является корректным отрицательным значением. - В случае, если разность значений больше 1, это приведет к отрицательным результатам.
Вместо этого вы можете использовать простую проверку, чтобы выявить отрицательные значения и заменить их на ноль или обработать иным образом:
tempCoh = pmax(1 - abs(tempData[i] - tempData), 0)
Это гарантирует, что все отрицательные значения будут приведены к нулю.
Заключение
Ошибки, которые у вас возникают, могут быть связаны с особенностями преобразования данных и вычисления результатов в R, а также с точностью вычислений с плавающей точкой. Я рекомендую провести детальную отладку кода, проверив промежуточные результаты после каждого шага. Если рекомендации выше не помогут решить вашу проблему, вам может понадобиться проверить реализацию функции likert_convert
и убедиться, что она работает как положено.