R (по-видимому) производит ошибки в расчетах

Вопрос или проблема

Это почти наверняка человеческие ошибки, но я не могу понять, что я делаю не так. Буду признателен за любые мысли.

Воспроизводимый пример:

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), то:

  1. Если x = 1 и y = -1, то tempCoh = 1 - abs(1 - (-1)) = 1 - 2 = -1, что является корректным отрицательным значением.
  2. В случае, если разность значений больше 1, это приведет к отрицательным результатам.

Вместо этого вы можете использовать простую проверку, чтобы выявить отрицательные значения и заменить их на ноль или обработать иным образом:

tempCoh = pmax(1 - abs(tempData[i] - tempData), 0)

Это гарантирует, что все отрицательные значения будут приведены к нулю.

Заключение

Ошибки, которые у вас возникают, могут быть связаны с особенностями преобразования данных и вычисления результатов в R, а также с точностью вычислений с плавающей точкой. Я рекомендую провести детальную отладку кода, проверив промежуточные результаты после каждого шага. Если рекомендации выше не помогут решить вашу проблему, вам может понадобиться проверить реализацию функции likert_convert и убедиться, что она работает как положено.

Оцените материал
Добавить комментарий

Капча загружается...