В R: Как заменить NA в векторе, найденном между двумя целыми числами - PullRequest
0 голосов
/ 04 марта 2019

У меня есть следующий вектор:

A:(NA NA NA NA 1 NA NA 4 NA NA 1 NA NA NA NA NA 4 NA 1 NA 4)

Я хотел бы заменить все Nas между 1 и 4 на 2 (но не Nas между 4 и 1)

Есть ликакие подходы вы бы порекомендовали / использовали для этой задачи?

Он также может управляться как фрейм данных:

 A 
----
 NA 
 NA 
 NA 
 NA 
 1 
 NA 
 NA 
 4 
 NA 
 NA 
 1 
 NA 
 NA 
 NA 
 NA 
 NA
 4 
 NA 
 1
 NA 
 4
----

Редактировать : 1. Я изменил строку "Na "to NA.

РЕШЕНИЕ / ОБНОВЛЕНИЕ Спасибо всем за ваши идеи.Я узнал от них, чтобы придумать следующее решение для моего случая.Я надеюсь, что это будет полезно для кого-то еще:

A <- c(df$A)

index.1<-which(df$A %in% c(1)) # define location for 1s in A
index.14<-which(df$A %in% c(1,4)) # define location for 1s and 4s in A

loc.1<-which(index.14 %in% index.1) # location of 1s in  index.14
loc.4<-loc.1+1 # location of 4s relative to 1s in index.14

start.i<-((index.14[loc.1])+1) # starting index for replacing with 2
end.i<-((index.14[loc.4])-1) # ending index for replacing with 2 in index

fill.v<-sort(c(start.i, end.i))# sequence of indexes to fill-in with # 2

# create matrix of beginning and ending sequence
fill.m<-matrix(fill.v,nrow = (length(fill.v)/2),ncol = 2, byrow=TRUE) 

# create a list with indexes to replace
list.1<-apply(fill.m, MARGIN=1,FUN=function(x) seq(x[1],x[2])) 

# unlist list to use as the indexes for replacement
list.2<-unlist(list.1) 

df$A[list.2] <- 2 # replace indexed location with 2

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Это должно сработать, и я предположил, что вы имеете в виду NA, а не строку "Na".Это будет работать либо для (хотя или смеси).

> A <- c(NA, NA, NA, NA, 1, NA, NA, 4, NA, NA, 1, NA, NA, NA, NA, NA, 4, NA, 1, NA, 4)
> 
> btw_1_4 <- unlist(lapply(Map(`:`, which(A == 1), which(A == 4)), function(x) x[2:(length(x)-1)]))
> 
> A[btw_1_4] <- 2
> 
> A
 [1] NA NA NA NA  1  2  2  4 NA NA  1  2  2  2  2  2  4 NA  1  2  4

Map(: , which(A == 1), which(A == 4))

Создает список позиций для 1-4 диапазонов в векторе (по порядку)

lapply(Map_List, function(x) x[2:(length(x)-1)]) Удаляетпервый и последний элемент каждого вектора в списке (позиции 1 и 4)

unlist превращает все оставшиеся позиции (NA между 1 и 4) в один вектор

0 голосов
/ 04 марта 2019

Предполагая, что A - это то, что воспроизводимо показано в примечании в конце, разность показанных консумированных значений дает значение ИСТИНА для элементов от 1 до 4 включительно, а следующее условие исключает конечные точки.Наконец, мы заменяем позиции, имеющие TRUE в том, что осталось, на 2.

replace(A, (cumsum(A == 1) - cumsum(A == 4)) & (A == "Na"), 2)

, давая:

 [1] "Na" "Na" "Na" "Na" "1"  "2"  "2"  "4"  "Na" "Na" "1"  "2"  "2"  "2"  "2" 
[16] "2"  "4"  "Na" "1"  "2"  "4"

Значения NA

R чувствительна к регистру, а Na - неттак же, как NA.Образцы данных в вопросе показали значения Na, а не значения NA, но если на самом деле подразумевался числовой вектор со значениями NA, как в AA в примечании ниже, то измените выражение так, как показано здесь:

replace(AA, cumsum(!is.na(AA) & AA == 1) - cumsum(!is.na(AA) & AA == 4) & is.na(AA), 2)

подача:

[1] NA NA NA NA  1  2  2  4 NA NA  1  2  2  2  2  2  4 NA  1  2  4

Примечание

A <- c("Na", "Na", "Na", "Na", "1", "Na", "Na", "4", "Na", "Na", 
"1", "Na", "Na", "Na", "Na", "Na", "4", "Na", "1", "Na", "4")

AA <- as.numeric(replace(A, A == "Na", NA))
0 голосов
/ 04 марта 2019

Я уверен, что есть лучшее решение этой проблемы, но это должно сработать:

A <-
  c(NA, NA, NA, NA, 1, NA, NA, 4, NA, NA, 1, NA, NA, NA, NA, NA, 4, NA, 1, NA, 4)

replace <- FALSE

for (i in 1:length(A)) {
  if (!is.na(A[i])) {
    if (A[i] == 1) {
      start <- i + 1
      replace <- TRUE
    }
    if (A[i] == 4 & replace == TRUE) {
      A[start:(i - 1)] <- 2
      replace <- FALSE
    }
  }
}

РЕДАКТИРОВАТЬ: , если вы хотите заменить только NA, еслинет ничего другого (например, 3) между 1 и 3, вы можете использовать это:

A <-
  c(NA, NA, NA, NA, 1, NA, 3, 4, NA, NA, 1, NA, NA, NA, NA, NA, 4, NA, 1, NA, 4)

replace <- FALSE

for (i in 1:length(A)) {
  if (!is.na(A[i])) {
    if (A[i] == 1) {
      start <- i + 1
      replace <- TRUE
    }
    if (A[i] == 4 & replace == TRUE) {
      A[start:(i - 1)] <- 2
      replace <- FALSE
    }
    if (A[i] != 4 & A[i] != 1){
      replace <- FALSE
    }
  }
}

Вывод:

> A
 [1] NA NA NA NA  1 NA  3  4 NA NA  1  2  2  2  2  2  4 NA  1  2  4

И если вы хотите заменить толькоNA, но сохраняют другие значения от 1 до 4, используют это:

A <-
  c(NA, NA, NA, NA, 1, NA, 3, 4, NA, NA, 1, NA, NA, NA, NA, NA, 4, NA, 1, NA, 4)

replace <- FALSE

for (i in 1:length(A)) {
  if (!is.na(A[i])) {
    if (A[i] == 1) {
      start <- i + 1
      replace <- TRUE
    }
    if (A[i] == 4 & replace == TRUE) {
      sub <- A[start:(i - 1)]
      sub[is.na(sub)] <- 2
      A[start:(i - 1)] <- sub
      replace <- FALSE
    }
  }
}

Вывод:

> A
 [1] NA NA NA NA  1  2  3  4 NA NA  1  2  2  2  2  2  4 NA  1  2  4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...