我有一个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")
我已使用NAs
包中的non-NA
用最接近的na.locf
替换了zoo
,但是我需要向替换的{{1} }值,以便最终产品看起来像这样:
NA
我写了一个小的> 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
答案 0 :(得分:3)
定义seq_let
,如果参数为全NA,则给出字母序列,其参数为长度,否则为“”。然后使用ave
和rleid
对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
答案 1 :(得分:2)
使用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
答案 2 :(得分:0)
从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