Измените значения в кадре данных по условию: длина объекта не кратна длине объекта - PullRequest
2 голосов
/ 04 июля 2019

Извините, я не смог найти правильный ответ в вопросах с длинна объекта не кратна длине объекта У меня есть такой фрейм данных

dt = data.frame(id = c(1,2,3,4,5), A=c('a', 'a', 'c', 'b','b'), B= c('d', 'd','h', 'd', 'd'))

И я хочу получить

  id A B final
1  1 a d  <NA>
2  2 a d     d
3  3 c h     c
4  4 b d     b
5  5 b d     d

Я

dt$A = ifelse(dt$A[dt$id] == dt$A[dt$id-1], as.character(dt$B[dt$id-1]), as.character(dt$A))
Warning message:
In dt$A[dt$id] == dt$A[dt$id - 1] :
  longer object length is not a multiple of shorter object length

Я могу сделать

shift <- function(x, n){
  c(x[-(seq(n))], rep(NA, n))
}

dt$sht <- shift(as.character(dt$A), 1)
dt$new = ifelse(dt$sht == dt$A, as.character(dt$B), as.character(dt$A[dt$id+1]))
temp = dt$new 
temp=append(NA, temp)
temp = temp[-6]
dt$final = temp
dt[, c(1,2,3,6)]

  id A B final
1  1 a d  <NA>
2  2 a d     d
3  3 c h     c
4  4 b d     b
5  5 b d     d

Но это долгий путь, я думаю, вы можете исправить ошибку в формуле

dt$A = ifelse(dt$A[dt$id] == dt$A[dt$id-1], as.character(dt$B[dt$id-1]), as.character(dt$A))

Или я буду благодарен за любой более удобный и короткий путь.

1 Ответ

2 голосов
/ 04 июля 2019

Индексирование в R начинается с 1. Когда мы берем dt$id -1, для 'id = 1 оно становится 0 и индексация с этим возвращает

dt$A[0]
#character(0)

, что приводит к разнице в length различных аргументов ifelse.

ifelse (тест, да, нет)

Если да или нет слишком короткие, их элементы перерабатываются. yes будет оцениваться тогда и только тогда, когда какой-либо элемент теста верен, и аналогично для no.


Вместо этого мы можем использовать lag

library(dplyr)
dt %>% 
    mutate(final = case_when(A == lag(A, default = A[1]) ~ lag(B), TRUE ~ A))
#  id A B final
#1  1 a d  <NA>
#2  2 a d     d
#3  3 c h     c
#4  4 b d     b
#5  5 b d     d

Здесь его также можно заменить на ifelse и в соответствии с ?case_when

Эта функция позволяет векторизовать несколько операторов if_else ().

данные

dt = data.frame(id = c(1,2,3,4,5), A=c('a', 'a', 'c', 'b','b'), 
   B= c('d', 'd','h', 'd', 'd'), stringsAsFactors = FALSE)

ПРИМЕЧАНИЕ: stringsAsFactors = TRUE, по умолчанию. Изменив его на FALSE, можно избежать нескольких преобразований as.character после создания набора данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...