Найти последнее вхождение уникальных значений в столбец и изменить значение в R

#r #dataframe

#r #фрейм данных

Вопрос:

У меня есть фрейм данных, как показано ниже

 a  b
5  0
5  0
5  0
6  0
6  0
  

Мне требуется отредактировать столбец b и изменить его на единицу в последнем экземпляре каждого уникального значения a . Пример ожидаемого результата,

 a  b
5  0
5  0
5  1
6  0
6  1
  

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

Ответ №1:

Несколько способов сделать это

 library(dplyr)

df %>%
  group_by(a) %>%
  mutate(b = if_else(row_number() == n(), 1L ,b))

#     a     b
#  <int> <dbl>
#1     5     0
#2     5     0
#3     5     1
#4     6     0
#5     6     1
  

То же использование ave

 with(df, ave(b, a, FUN = function(x) ifelse(seq_along(x) == length(x), 1, x)))
  

Редактировать

В случае, если у вас столбцы в виде символов, нам нужно сначала преобразовать их в числовые и использовать if_else

 df %>%
  mutate_all(as.numeric) %>%
  group_by(a) %>%
  mutate(b = if_else(row_number() == n(), 1 ,b))
  

Или просто используйте ifelse , поскольку это не зависит от строгой проверки типа

 df %>%
  group_by(a) %>%
  mutate(b = ifelse(row_number() == n(), 1 ,b))
  

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

1. Я получаю сообщение об ошибке: false имеет тип ‘character’, а не ‘integer’, когда я запускаю команду

2. @Visahan, кажется, у вас есть b в качестве символа, о, вам нужно преобразовать его в числовое значение или просто использовать ifelse тогда , df %>% group_by(a) %>% mutate(b = ifelse(row_number() == n(), 1 ,b))

Ответ №2:

Используйте duplicated и установите fromLast значение быть TRUE , чтобы начать поиск с конца a .

 with(df1, replace(b, !duplicated(a, fromLast = TRUE), 1))
#[1] 0 0 1 0 1
  

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

1. Спасибо за быстрый ответ, но если вы не возражаете, не могли бы вы предоставить краткое описание уравнения? Это будет действительно полезно

2. Хотя эта команда устанавливает значение ‘1’ в правильные строки, все 0 изменяются на NA. Я знаю, что могу использовать ‘df1 $ b[is.na (df1 $ b)] <- 0’, чтобы вернуть им значение 0, но это кажется неэффективным.

3. Я не видел, чтобы вы использовали duplicated . Вы можете сделать его компактным, чтобы as.integer(!duplicated(df1$a, fromLast = TRUE))

4. @Visahan Этот вариант может быть понятнее? transform(df1, b = replace(b, !duplicated(a, fromLast=TRUE), 1)) Вы можете прочитать ?duplicated , ?replace , ?transform и т. Д

Ответ №3:

Вы могли бы выполнить объединение в последней строке:

 library(data.table)
setDT(DT)

DT[.(unique(a)), on=.(a), mult="last", b := 1]

   a b
1: 5 0
2: 5 0
3: 5 1
4: 6 0
5: 6 1
  

Синтаксис x[i, on=, j] .

  • Он просматривает каждую строку i в x с использованием условий объединения on= .
  • При наличии нескольких совпадений для строки i используется последнее.
  • В j мы обновляем b в x соответствующие строки.