Добавить инкрементную букву к заполненным NA от na.locf () - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть 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, но мне нужнодобавить добавочную букву к замененным значениям 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 оператор ничего не делает.Любые предложения приветствуются.

> 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 = "")
+     }
+ }

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

Делай с 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
0 голосов
/ 21 февраля 2019

Заимствование кода из Создание счетчика в последовательных прогонах определенных значений :

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, выбирая основную идею из: Подсчет последовательных ИСТИННЫХ значенийвнутри каждого блока отдельно

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
0 голосов
/ 21 февраля 2019

Определите seq_let, который дает последовательности букв длину своего аргумента, если его аргумент равен NA и "" в противном случае.Затем сгруппируйте NA и не-NA, используя ave и rleid, и примените 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...