Существует ли функция R, которая удалит последнее значение каждой строки?

#r #dplyr

Вопрос:

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

Эти данные имеют разную длину и имеют множество различных значений:

 My data looks somewhat like this. 

df <- data.frame(
  weight_1 = c(43L, 2L, 6L, 30L, 69L, 82L, 98L, 79L, 68L),
  weight_2 = c(60L, 40L, 78L, 48L, 75L, 77L, 55L, 3L, 66L),
  weight_3 = c(22L, 4L, 77L, 40L, 91L, 57L, 34L, 84L, NA),
  weight_4 = c(88L, 47L, 77L, 82L, 31L, 19L, 11L, NA, NA),
  weight_5 = c(80L, 65L, 12L, 17L, 62L, 95L, NA, NA, NA),
  weight_6 = c(95L, 71L, 14L, 29L, 66L, 83L, NA, NA, NA),
  weight_7 = c(64L, 20L, 69L, 57L, NA, NA, NA, NA, NA),
  weight_8 = c(45L, 19L, NA, NA, NA, NA, NA, NA, NA)
)
 

Я нашел значение последней строки, используя

 
final_row <- as.data.frame(df[cbind( 1:nrow(df), max.col(!is.na(df),"last") )])
colnames(final_row)[1] <- "last_value"
 

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

Комментарии:

1. Было бы полезно предоставить образец ваших данных, используя dput() их и делясь ими в рамках вашего вопроса, чтобы сделать их воспроизводимыми. Бесцеремонно я бы сказал, что вам нужно добавить переменную id , чтобы отслеживать использование респондентами row_number() , затем преобразовать данные в длинный формат , используя pivot_longer() из tidyr пакета, затем удалить NAs с drop_na() , а затем отфильтровать любую строку с последним значением filter() . Но опять же, было бы проще показать, как с реальными данными работать.

Ответ №1:

Возможно, вы этого хотите?

 df <- data.frame(
  weight_1 = c(43L, 2L, 6L, 30L, 69L, 82L, 98L, 79L, 68L),
  weight_2 = c(60L, 40L, 78L, 48L, 75L, 77L, 55L, 3L, 66L),
  weight_3 = c(22L, 4L, 77L, 40L, 91L, 57L, 34L, 84L, NA),
  weight_4 = c(88L, 47L, 77L, 82L, 31L, NA, 19L, 11L, NA),
  weight_5 = c(80L, 65L, 12L, 17L, 62L, NA, 40L, 95L, NA),
  weight_6 = c(95L, 71L, 14L, NA, 29L, NA, 66L, 83L, NA),
  weight_7 = c(64L, 20L, NA, NA, 69L, NA, 57L, NA, NA),
  weight_8 = c(45L, NA, NA, NA, NA, NA, 19L, NA, NA)
)
library(dplyr, warn.conflicts = F)
df %>% 
  mutate(across(everything(), ~ifelse(cur_column() == names(df)[max.col(!is.na(df), ties.method = 'last')], NA, .)))
#>   weight_1 weight_2 weight_3 weight_4 weight_5 weight_6 weight_7 weight_8
#> 1       43       60       22       88       80       95       64       NA
#> 2        2       40        4       47       65       71       NA       NA
#> 3        6       78       77       77       12       NA       NA       NA
#> 4       30       48       40       82       NA       NA       NA       NA
#> 5       69       75       91       31       62       29       NA       NA
#> 6       82       77       NA       NA       NA       NA       NA       NA
#> 7       98       55       34       19       40       66       57       NA
#> 8       79        3       84       11       95       NA       NA       NA
#> 9       68       NA       NA       NA       NA       NA       NA       NA
 

Создано 2021-07-19 пакетом reprex (v2.0.0)


более ранний ответ

 df <- data.frame(
    weight_1 = c(43L, 2L, 6L, 30L, 69L, 82L, 98L, 79L, 68L),
    weight_2 = c(60L, 40L, 78L, 48L, 75L, 77L, 55L, 3L, 66L),
    weight_3 = c(22L, 4L, 77L, 40L, 91L, 57L, 34L, 84L, NA),
    weight_4 = c(88L, 47L, 77L, 82L, 31L, NA, 19L, 11L, NA),
    weight_5 = c(80L, 65L, 12L, 17L, 62L, NA, 40L, 95L, NA),
    weight_6 = c(95L, 71L, 14L, NA, 29L, NA, 66L, 83L, NA),
    weight_7 = c(64L, 20L, NA, NA, 69L, NA, 57L, NA, NA),
    weight_8 = c(45L, NA, NA, NA, NA, NA, 19L, NA, NA)
      )

df
#>   weight_1 weight_2 weight_3 weight_4 weight_5 weight_6 weight_7 weight_8
#> 1       43       60       22       88       80       95       64       45
#> 2        2       40        4       47       65       71       20       NA
#> 3        6       78       77       77       12       14       NA       NA
#> 4       30       48       40       82       17       NA       NA       NA
#> 5       69       75       91       31       62       29       69       NA
#> 6       82       77       57       NA       NA       NA       NA       NA
#> 7       98       55       34       19       40       66       57       19
#> 8       79        3       84       11       95       83       NA       NA
#> 9       68       66       NA       NA       NA       NA       NA       NA
library(dplyr, warn.conflicts = F)

df %>% rowwise() %>%
  summarise(last_col = last(na.omit(c_across(everything()))), .groups = 'drop')
#> # A tibble: 9 x 1
#>   last_col
#>      <int>
#> 1       45
#> 2       20
#> 3       14
#> 4       17
#> 5       69
#> 6       57
#> 7       19
#> 8       83
#> 9       66
 

Создано 2021-07-17 пакетом reprex (v2.0.0)

Комментарии:

1. Я уже нашел последние значения (извините, если это было неясно), но это еще один отличный пример того, как их найти. Я ищу, чтобы заменить или отфильтровать последнее найденное значение.

2. @ДжефФроули, см. пересмотренный ответ

Ответ №2:

Для замены последнего значения, отличного от NA, в каждой строке на NA вы можете использовать apply в базе R —

 df[] <- t(apply(df, 1, function(x) {
             x[max(which(!is.na(x)))] <- NA
             x
       }))