Вопрос или проблема
Я хочу, чтобы моя переменная ttA была меньшей из TIME_TO_A и TIME_TO_B. Но этот код, похоже, рассматривает целые столбцы, а не только значение для каждой отдельной строки. В данный момент, каждый раз, когда TIME_TO_A <= 183, он возвращает 0.
data6mo <- data %>%
mutate(ttA =
case_when(
TIME_TO_A > 183 ~ 183,
TIME_TO_A <= 183 ~ min(TIME_TO_A, TIME_TO_B, na.rm = TRUE)
))
Используйте функцию pmin()
library(dplyr)
data <- data.frame(
time_to_a = c(100, 130, 185, 200),
time_to_b = c(70, 160, 185, 200)
)
data
#> time_to_a time_to_b
#> 1 100 70
#> 2 130 160
#> 3 185 185
#> 4 200 200
data6mo <- data %>%
mutate(
ttA = case_when(
time_to_a > 183 ~ 183,
time_to_a <= 183 ~ pmin(time_to_a, time_to_b, na.rm = TRUE)
)
)
data6mo
#> time_to_a time_to_b ttA
#> 1 100 70 70
#> 2 130 160 130
#> 3 185 185 183
#> 4 200 200 183
Создано 2024-10-22 с помощью reprex v2.0.2
В базовом R:
transform(data, a = pmin(time_to_a, time_to_b, 183))
time_to_a time_to_b a
1 100 70 70
2 130 160 130
3 185 185 183
4 200 200 183
Согласно логике в вашей попытке кода, я думаю, что ifelse
+ pmin
должны хорошо сработать
(Обратите внимание, смотрите фиктивные данные в пятой строке, что является краевым случаем, упомянутым в комментарии @Johan Rosa к @решению Onyambu)
> transform(data, ttA = ifelse(time_to_a > 183, 183, pmin(time_to_a, time_to_b)))
time_to_a time_to_b ttA
1 100 70 70
2 130 160 130
3 185 185 183
4 200 200 183
5 185 70 183
или один из его вариантов, например,
> transform(data, ttA = 183 * (time_to_a > 183) + pmin(time_to_a, time_to_b) * (time_to_a <= 183))
time_to_a time_to_b ttA
1 100 70 70
2 130 160 130
3 185 185 183
4 200 200 183
5 185 70 183
Данные
data <- data.frame(
time_to_a = c(100, 130, 185, 200, 185),
time_to_b = c(70, 160, 185, 200, 70)
)
.
Ответ или решение
Как правильно вернуть минимальное значение из двух переменных в R
Ситуация, с которой вы столкнулись, касается определения минимального значения между двумя переменными TIME_TO_A и TIME_TO_B в строки данных, при этом необходимо учитывать условие: если TIME_TO_A превышает 183, возвращать 183. Ваша начальная попытка с использованием функции min
использует весь столбец, вместо того чтобы смотреть на отдельные строки. Это распространённая проблема, которая может возникнуть при работе с колоночными операциями в dplyr
.
Подход с использованием pmin()
Наиболее эффективный и простой способ решения вашей задачи — использовать функцию pmin()
, которая возвращает поэлементное минимальное значение из нескольких векторов. Функция pmin()
позволяет значительно упростить вашу логику и сделать код более читаемым.
Вот пример кода, который вы можете использовать:
library(dplyr)
data <- data.frame(
time_to_a = c(100, 130, 185, 200),
time_to_b = c(70, 160, 185, 200)
)
data6mo <- data %>%
mutate(
ttA = case_when(
time_to_a > 183 ~ 183,
TRUE ~ pmin(time_to_a, time_to_b, na.rm = TRUE)
)
)
print(data6mo)
Ожидаемый результат
При выполнении этого кода вы получите следующий вывод:
time_to_a time_to_b ttA
1 100 70 70
2 130 160 130
3 185 185 183
4 200 200 183
Этот подход работает следующим образом:
- Если time_to_a больше 183, то возвращается фиксированное значение 183.
- Если же time_to_a меньше или равно 183, используется
pmin
для расчета минимального значения между time_to_a и time_to_b.
Альтернативные методы
Вы также можете решить эту задачу с использованием базового R или комбинации ifelse
и pmin
. Вот пример с использованием ifelse
:
data6mo <- transform(data, ttA = ifelse(time_to_a > 183, 183, pmin(time_to_a, time_to_b, na.rm = TRUE)))
Или путем комбинирования логических условий:
data6mo <- transform(data, ttA = 183 * (time_to_a > 183) + pmin(time_to_a, time_to_b) * (time_to_a <= 183))
Заключение
Использование pmin()
— это простой, понятный и эффективный способ вернуть минимальное значение между двумя переменными для каждой строки, предоставляя вам необходимую гибкость в обработке условий. Убедитесь, что вы подключили пакет dplyr
, чтобы использовать такие функции, и всегда проверяйте ваши данные на наличие пропусков, чтобы избежать неожиданных результатов.
Если у вас остались вопросы или есть необходимость в более глубоком разборе, не стесняйтесь задавать их!