Изменение условий для замены элементов в векторе - PullRequest
6 голосов
/ 14 января 2020

Рассмотрим вектор:

use = c(1,1,2,2,5,1,2,1,2,5,1)

Я пытаюсь заменить все числа, отличающиеся от 5, до NA, прежде чем первое число 5 появится в последовательности: ifelse(use != 5,NA,1) , После этого условие должно быть ifelse(use != 5,0,1).

Вывод будет:

after = c(NA,NA,NA,NA,1,0,0,0,0,1,0)

Любые советы?

Ответы [ 9 ]

3 голосов
/ 15 января 2020

Вы должны попробовать:

`is.na<-`(match(use, 5, 0), seq(match(5, use) - 1))
 [1] NA NA NA NA  1  0  0  0  0  1  0
2 голосов
/ 15 января 2020

Странное подмножество:

c(NA[!cumsum(use == 5)], +(use[!!cumsum(use == 5)] == 5))
#[1] NA NA NA NA  1  0  0  0  0  1  0
2 голосов
/ 14 января 2020

Мы можем использовать match

replace(use, seq_len(match(5, use) - 1), NA)
#[1] NA NA NA NA  5  1  2  1  2  5  1

Или, как прокомментировал @ M--, это можно изменить на двоичный файл с

+(replace(use, seq_len(match(5, use) - 1), NA)==5)
1 голос
/ 15 января 2020

Вот базовое решение R

after <- replace(v<- ifelse(use !=5,NA,1),
        which(head(which(v==1),1)<seq_along(v) & is.na(v)),
        0)

такое, что

> after
 [1] NA NA NA NA  1  0  0  0  0  1  0
1 голос
/ 14 января 2020

Вот еще один вариант. Я в некоторой обработке ошибок в случае, если нет 5 в векторе.

test1 <-  c(1,1,1,1,2,3,3)
test2 <-  c(5,1,1,2,5,1,2,7,8)
test3 <-  c(1,1,3,5,6,7,8,2)
test4 <-  c(1,2,3,4,5,5,1,5,5,5,1,1,7,8,1)



find_and_replace <- function(vec, target){
  tryCatch(
    ifelse( seq_along(vec) %in% 1:{(which(vec == target)[[1]])-1}, NA, ifelse(vec == 5, 1, 0)),
    error = function(x) {
      warning(paste("Warning: No", target))
      vec
    }
  )
}

find_and_replace(test1, 5)
#> Warning: No 5
#> [1] 1 1 1 1 2 3 3
find_and_replace(test2, 5)
#> [1] NA  0  0  0  1  0  0  0  0
find_and_replace(test3, 5)
#> [1] NA NA NA  1  0  0  0  0
find_and_replace(test4, 5)
#> [1] NA NA NA NA  1  1  0  1  1  1  0  0  0  0  0
1 голос
/ 14 января 2020

Следующий код решает проблему:

use[1:(which(use == 5)[1]-1)] = NA
use[(which(use == 5)[1]+1):length(use)] = 0
use[which(use == 5)[1]] = 1
use
[1] NA NA NA NA  1  0  0  0  0
1 голос
/ 14 января 2020

Это будет работать, если в вашем векторе есть только одна 5

use = c(1,1,2,2,5,1,2,2,2)
use <- findInterval(use,5)*5
i <- which(use > 0)
if(i > 1) use[1:(i-1)] <- NA
1 голос
/ 14 января 2020

Вы можете использовать which, чтобы найти местоположение цели, а затем case_when

use <- c(1,1,2,2,5,1,2,1,2)

first_five <- min(which(use == 5))
dplyr::case_when(
  seq_along(use) < first_five ~ NA_real_,
  seq_along(use) == first_five ~ 1, 
  TRUE ~ 0
)
#> [1] NA NA NA NA  1  0  0  0  0
use
#> [1] 1 1 2 2 5 1 2 1 2

Создано в 2020-01-14 пакетом Представить (v0.3.0)

0 голосов
/ 14 января 2020

Вы можете обнаружить первые 5,

first_pos <- which(use==5)

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

if(length(first_pos)>0) {
    use[seq(1,first_pos[1]-1)] <- NA
    use[seq(1,first_pos[1])] <- 1
    use[seq(first_pos[1]+1, length(use)] <- 0
}

Обратите внимание, что first_pos[1] вызывается в случае, если существует более одного 5.

...