#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
соответствующие строки.