[英]Replace NA value with next or previous non-NA value conditional on other column
以下是与我正在使用的数据类似的示例数据集。
df<-data.frame(Loc=c(rev(seq(-4,5,1)),seq(-4,5,1)),
Reg=c("A",rep(NA,8),"B",rep(NA,9),"C"))
在此示例中,我们具有从+到-值范围的字符串,反之亦然(Loc)。 我要完成的工作是填充这些NA值,其中B始终与Loc的负值相关联,但是,如果NA在A和B之间,则正值可以取值A;如果NA在B之间,则C可以取值C。和C。
所需的输出应如下所示
df2<-data.frame(Loc=c(rev(seq(-4,5,1)),seq(-4,5,1)),
Reg=c(rep("A",6),rep("B",8),rep("C",6)))
我已经从zoo包中调查了na.locf,但是我不确定如何命令该函数在哪个方向上寻找非NA值以获得所需的输出。
df$Reg2<-ifelse(df$Loc<=0,df$Reg2<-"B",na.locf(df$Reg,fromLast = F))
上面的代码仅根据方向返回某些行的正确响应(即fromLast = T或F)
任何帮助,将不胜感激。
通过从符号的rleid
生成的分组变量使用ave
rleid
。 然后省略NA,在每个组中保留单个非NA, ave
将复制该组中的所有值。
library(data.table)
transform(df, Reg = ave(Reg, rleid(Loc >= 0), FUN = na.omit))
给予:
Loc Reg
1 5 A
2 4 A
3 3 A
4 2 A
5 1 A
6 0 A
7 -1 B
8 -2 B
9 -3 B
10 -4 B
11 -4 B
12 -3 B
13 -2 B
14 -1 B
15 0 C
16 1 C
17 2 C
18 3 C
19 4 C
20 5 C
这是一个data.table
解决方案,它再现了OP的预期答案:
library(data.table)
result <- as.data.table(df)[, Reg := first(Reg[!is.na(Reg)]), by = rleid(Loc >= 0)][]
result
Loc Reg 1: 5 A 2: 4 A 3: 3 A 4: 2 A 5: 1 A 6: 0 A 7: -1 B 8: -2 B 9: -3 B 10: -4 B 11: -4 B 12: -3 B 13: -2 B 14: -1 B 15: 0 C 16: 1 C 17: 2 C 18: 3 C 19: 4 C 20: 5 C
identical(as.data.frame(result), df2)
[1] TRUE
请注意,此方法与G. Grothendiek的基本R解决方案相似,因为它使用rleid(Loc >= 0)
对数据进行分组,但它不调用transform()
和ave()
而是通过引用更新Reg
,即不进行复制整个对象。
这是dplyr的快速解决方案:
df<-data.frame(Loc=c(rev(seq(-4,5,1)),seq(-4,5,1)),
Reg=c("A",rep(NA,8),"B",rep(NA,9),"C"))
c <- match("C",df$Reg)
a <- match("A",df$Reg)
df2 <- df %>%
mutate(newReg=case_when(Loc < 0 ~ "B",
Loc >= 0 & abs(row_number()-c)<abs(row_number()-a)~ "C",
TRUE ~ "A"))
注意:这很可怕,我怀疑这是否可以在更多用例中重现……这可能更适合某些类型的dplyr::case_when
函数,但是我dplyr::case_when
。
lapply(2:nrow(df), function(i){
this_row <- df[i, ]
last_row <- i - 1
if(is.na(this_row[['Reg']])){
if(this_row[['Loc']] < 0){
df[i, 'Reg'] <<- "B"
}else if(df[i - 1, 'Reg'] == "A"){
df[i, 'Reg'] <<- "A"
}else {
df[i, "Reg"] <<- "C"
}
}
})
> df
Loc Reg
1 5 A
2 4 A
3 3 A
4 2 A
5 1 A
6 0 A
7 -1 B
8 -2 B
9 -3 B
10 -4 B
11 -4 B
12 -3 B
13 -2 B
14 -1 B
15 0 C
16 1 C
17 2 C
18 3 C
19 4 C
20 5 C
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.