按条件更改数据框中的值:较长的对象长度不是较短对象长度的倍数

Change values in dataframe by condition: longer object length is not a multiple of shorter object length

抱歉,在 较长的对象长度不是较短的对象长度的倍数的问题中,我找不到正确答案 我有一个这样的数据框

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))

或者,如果有任何更方便、更短的方式,我将不胜感激。

R中的索引从1开始。当我们取dt$id -1时,对于'id =1,它变成0并用returns

索引
dt$A[0]
#character(0)

导致 ifelse 的不同参数的 length 不同。

ifelse(test, yes, no)

If yes or no are too short, their elements are recycled. yes will be evaluated if and only if any element of test is true, and analogously for 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

This function allows you to vectorise multiple if_else() statements.

数据

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转换