#r #dplyr
Вопрос:
Я пытаюсь отметить ближайшее количество дней от несчастного случая до того момента, когда кто-то получил страховку. 0 означает тот же день, отрицательное число представляет страховку до несчастного случая, а положительное число представляет страховку после несчастного случая.
Данные
df lt;- data.frame(id=1:4, accident1=c(-1,3,4, NA), accident2=c(100, -2, NA, NA), accident3=c(-3,1,2, NA)) gt; df id accident1 accident2 accident3 1 1 -1 100 -3 2 2 3 -2 1 3 3 4 NA 2 4 4 NA NA NA
Код:
library(DescTools) library(dplyr) df %gt;% rowwise() %gt;% mutate(magic= case_when( accident1 lt;0 |accident2lt;0 |accident3lt;0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), accident1 gt;0 |accident2gt;0 | accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 gt; 0 amp; accident2 gt; 0 amp; accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 lt; 0 amp; accident2 lt; 0 amp; accident3 lt; 0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), TRUE ~ NA_real_)) %gt;% rowwise() %gt;% # not working mutate(magic= case_when( (accident1 gt;0 |accident2lt;0 |accident3lt;0) amp; (accident1 gt;0 |accident2gt;0 | accident3gt;0) ~ Closest(as.numeric(unlist(c(accident1, accident2, accident3))), 0, na.rm=T), TRUE~magic))
Результат без последней строки в данных (все NAs):
# A tibble: 3 × 5 # Rowwise: id accident1 accident2 accident3 magic lt;intgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; 1 1 -1 100 -3 -1 2 2 3 -2 1 1 3 3 4 NA 2 2
Однако, когда я попробую это с NA в последнем ряду:
Error: Problem with `mutate()` column `magic`. ℹ `magic = case_when(...)`. ℹ `magic` must be size 1, not 0. ℹ Did you mean: `magic = list(case_when(...))` ? ℹ The error occurred in row 4. Run `rlang::last_error()` to see where the error occurred. In addition: Warning message: Problem with `mutate()` column `magic`. ℹ `magic = case_when(...)`. ℹ no non-missing arguments to min; returning Inf ℹ The warning occurred in row 4.
Есть какие-нибудь советы о том, как заставить код работать в строке 4 с NAs?
Ответ №1:
Основная причина-последний элемент, который возвращается numeric(0)
, потому что все элементы есть NA
, и мы использовали na.rm = TRUE
для Closest
. Мы можем предотвратить это, индексируя, чтобы вернуть первый элемент, и это изменится на NA
library(dplyr) df %gt;% mutate(magic= case_when( accident1 lt;0 |accident2lt;0 |accident3lt;0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), accident1 gt;0 |accident2gt;0 | accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 gt; 0 amp; accident2 gt; 0 amp; accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 lt; 0 amp; accident2 lt; 0 amp; accident3 lt; 0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), TRUE ~ NA_real_)) %gt;% rowwise() %gt;% mutate(magic= case_when( (accident1 gt;0 |accident2lt;0 |accident3lt;0) amp; (accident1 gt;0 |accident2gt;0 | accident3gt;0) ~ Closest(as.numeric(unlist(c(accident1, accident2, accident3))), 0, na.rm=TRUE)[1], TRUE~magic))
-выход
# A tibble: 4 × 5 # Rowwise: id accident1 accident2 accident3 magic lt;intgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; 1 1 -1 100 -3 -1 2 2 3 -2 1 1 3 3 4 NA 2 2 4 4 NA NA NA NA
Это будет легче понять, если мы будем делать это только на Closest
gt; apply(df[-1], 1, function(x) Closest(x, 0, na.rm = TRUE)) [[1]] accident1 -1 [[2]] accident3 1 [[3]] accident3 2 [[4]] named numeric(0) ####
Решение индексирует, так что numeric(0)
становится NA
numeric(0)[1] [1] NA
Ответ №2:
Я хочу дать немного больше объяснений относительно того, почему ваш первоначальный подход не сработал, и ответ @akrun работает. Во-первых, давайте сохраним результаты первого mutate
.
interim lt;- df %gt;% rowwise() %gt;% mutate( magic= case_when( accident1 lt; 0 | accident2 lt; 0 | accident3 lt; 0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), accident1 gt;0 | accident2gt;0 | accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 gt; 0 amp; accident2 gt; 0 amp; accident3gt;0 ~ as.numeric(pmin(accident1, accident2, accident3, na.rm=T)), accident1 lt; 0 amp; accident2 lt; 0 amp; accident3 lt; 0 ~ as.numeric(pmax(accident1, accident2, accident3, na.rm=T)), TRUE ~ NA_real_))
Проблема возникает из case_when
-за того, что lhs и rhs оцениваются отдельно. Т. Е. он вычисляет потенциальные значения для каждого случая, а затем выбирает, какое из них возвращать. Следовательно, каждая lhs должна предоставлять результат для каждого возможного входного значения, независимо от того, используется ли оно на самом деле.
Вместо Closest
этого возьмите простую функцию , которая всегда возвращает одно и то же значение.
alwaysComputes lt;- function(x) 4.2 interim %gt;% mutate( magic = case_when( (accident1 gt;0 |accident2lt;0 |accident3lt;0) amp; (accident1 gt;0 |accident2gt;0 | accident3gt;0) ~ alwaysComputes(magic), TRUE~magic ) ) #gt; # A tibble: 4 x 5 #gt; # Rowwise: #gt; id accident1 accident2 accident3 magic #gt; lt;intgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; #gt; 1 1 -1 100 -3 4.2 #gt; 2 2 3 -2 1 4.2 #gt; 3 3 4 NA 2 4.2 #gt; 4 4 NA NA NA NA
Никаких проблем, потому что даже для NA
функции всегда возвращается значение 4.2. case_when
просто не возвращает значение 4.2, рассчитанное для строки 4.
Если мы изменим функцию, чтобы возвращать только значения, отличные от NA, мы повторно создадим ошибку:
condComputes lt;- function(x) if(is.na(x)) stop("problems") else x interim %gt;% mutate( magic = case_when( (accident1 gt;0 |accident2lt;0 |accident3lt;0) amp; (accident1 gt;0 |accident2gt;0 | accident3gt;0) ~ condComputes(magic), TRUE~magic ) ) #gt; Error: Problem with `mutate()` input `magic`. #gt; x problems #gt; i Input `magic` is `case_when(...)`. #gt; i The error occurred in row 4.
В вашем первоначальном подходе lhs для первого случая возвращает вектор длины 0 для строки 4. Даже если это в конечном итоге будет отброшено, case_when
он не знает, что оно будет отброшено во время его вычисления, и поэтому возникает ошибка. решение @akrun заставляет возвращать либо NA, либо первое/единственное значение (поскольку в R нет скалярных значений)