从 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.locf
将 NAs
替换为最近的 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 则给出其参数长度的字母序列,否则为 ""。然后使用 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
使用 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
我有一个 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.locf
将 NAs
替换为最近的 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 则给出其参数长度的字母序列,否则为 ""。然后使用 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
使用 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