从 na.locf() 向填充的 NA 添加增量字母

Add an incremental letter to filled NAs from na.locf()

我有一个 data.frame 看起来像这样:

df <- structure(list(
  a = c("atg", "tga", "agt", "acc", "cgt", "gca",
    "gtc", "ggg", "ccc"),
  b = c("1", "2", NA, "3", NA, NA, "4", "5",
    "6")
),
row.names = c(NA, -9L),
class = "data.frame")

我已经使用 zoo 包中的 na.locfNAs 替换为最近的 non-NA,但我需要向替换的 [= 添加一个增量字母19=] 值,所以最终产品看起来像这样:

> df
    a    b
1 atg    1
2 tga    2
3 agt    2a
4 acc    3
5 cgt    3a
6 gca    3b
7 gtc    4
8 ggg    5
9 ccc    6

我写了一个小的 if 函数,它适当地填充 NA,但向所有值添加字母并回收数字以匹配 letters 的长度。我可以看到这个结果来自函数中的 any 调用我现在认为我可能需要做一个 for 循环并使用它来递增每个单元格,但是 for使用 if 语句变体的循环不执行任何操作。欢迎提出任何建议。

> testif <- function(x) {
+   if (any(is.na(x)))  {
+     paste(na.locf(x), letters, sep = "")
+   }
+ }

for (x in df$b)     {
+     if (any(is.na(x)))  {
+         paste(test$b, na.locf(x), letters, sep = "")
+     }
+ }

定义 seq_let 如果其参数全部为 NA 则给出其参数长度的字母序列,否则为 ""。然后使用 averleid 对 NA 和非 NA 运行进行分组,并将 seq_let 应用到每个组前加上 na.locf0(b)。

library(data.table)
library(zoo)

seq_let <- function(x) if (all(is.na(x))) letters[seq_along(x)] else ""
transform(df, b = paste0(na.locf0(b), ave(b, rleid(is.na(b)), FUN = seq_let)))

给予:

    a  b
1 atg  1
2 tga  2
3 agt 2a
4 acc  3
5 cgt 3a
6 gca 3b
7 gtc  4
8 ggg  5
9 ccc  6

使用 zoo 和基础 R

x=zoo::na.locf(df$b)
s=as.numeric(ave(x,x,FUN=function(x) seq_along(x)))-1
x[s!=0]=paste0(x[s!=0],letters[s])
df$b=x
df
    a  b
1 atg  1
2 tga  2
3 agt 2a
4 acc  3
5 cgt 3a
6 gca 3b
7 gtc  4
8 ggg  5
9 ccc  6

Create counter within consecutive runs of certain values借用代码:

i <- is.na(df$b)
g <- cumsum(i)
df$b <- paste0(na.locf(df$b), c("", letters)[g - cummax((!i) * g) + 1])

#     a  b
# 1 atg  1
# 2 tga  2
# 3 agt 2a
# 4 acc  3
# 5 cgt 3a
# 6 gca 3b
# 7 gtc  4
# 8 ggg  5
# 9 ccc  6

使用 data.table 更紧凑,从中挑选主要思想:Count consecutive TRUE values within each block separately

library(data.table)

setDT(df)[ ,  b := paste0(na.locf(b), c("", letters)[rowid(rleid(b)) * is.na(b) + 1])]

#      a  b
# 1: atg  1
# 2: tga  2
# 3: agt 2a
# 4: acc  3
# 5: cgt 3a
# 6: gca 3b
# 7: gtc  4
# 8: ggg  5
# 9: ccc  6