Фильтровать фрейм данных на основе фиксированного рейтинга с сохранением NA

#r

#r

Вопрос:

давайте сначала создадим пример

 scale1 <- c(5,NA,2,1)
scale2 <- c(NA,4,NA,3)
scale3 <- c(3,NA,5,NA)
scale4 <- c(2,1,NA,5)
df<- data.frame(scale1,scale2,scale3,scale4)
df
  

Вот результат

 ##    scale1 scale2 scale3 scale4
#1      5     NA      3      2
#2      NA     4     NA     1
#3      2     NA      5     NA
#4      1      3     NA      5
  

Вот что я застрял.

Я провожу опрос, в котором участники должны оценивать по нескольким шкалам. Предполагается, что значение scale в этом порядке с

масштаб 1 > = масштаб 2 > = масштаб 3 > = масштаб 4

поэтому я хочу удалить тех, кто нарушил этот порядок, сохранив NA (поскольку шкалы назначаются случайным образом)

Вывод должен выглядеть следующим образом (случай 3 и 4 удалены)

 ##    scale1 scale2 scale3 scale4
#1      5     NA      3      2
#2      NA     4     NA     1
  

Есть ли эффективный способ добиться этого (поскольку у меня много наборов масштабов в моих фактических данных)

Спасибо!

Ответ №1:

Вы можете сделать это с помощью row-wise apply :

 cols <- grep('scale', names(df))
df[apply(df[cols], 1, function(x) all(diff(na.omit(x)) < 0)), ]

#  scale1 scale2 scale3 scale4
#1      5     NA      3      2
#2     NA      4     NA      1
  

и то же самое с использованием dplyr :

 library(dplyr)
df %>%
  rowwise() %>%
  filter(all(diff(na.omit(c_across(starts_with('scale')))) < 0 ))
  

При этом выбираются строки, в которых все значения в строке меньше предыдущего значения в строке.

данные

 df <- structure(list(scale1 = c(5, NA, 2, 1), scale2 = c(NA, 4, NA, 
3), scale3 = c(3, NA, 5, NA), scale4 = c(2, 1, NA, 5)), 
class = "data.frame", row.names = c(NA, -4L))