更改条件以替换向量中的元素

Posted

技术标签:

【中文标题】更改条件以替换向量中的元素【英文标题】:Changing the conditions to replace elements in a vector 【发布时间】:2020-05-01 12:15:27 【问题描述】:

考虑向量:

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

在第一个数字 5 出现在序列中之前,我正在尝试将所有不同于 5 的数字替换为 NA: ifelse(use != 5,NA,1)。 之后的条件应该是 ifelse(use != 5,0,1)

输出将是:

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

有什么建议吗?

【问题讨论】:

为什么use 的长度是11 而after 的长度是9? after 中是否应该有两个 1,因为 use 中有两个 5? 【参考方案1】:

你可以使用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

由reprex package (v0.3.0) 于 2020 年 1 月 14 日创建

【讨论】:

谢谢@RichardTelford!但在第一个算法 5 出现后,我还需要ifelse(use != 5,0,1) 现在已修复以匹配所需的输出【参考方案2】:

如果您的向量中只有一个 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

【讨论】:

【参考方案3】:

你可以检测到前 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。

【讨论】:

【参考方案4】:

下面的代码解决了这个问题:

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

【讨论】:

嗨@FilipeLauar 如果向量中的 5 超过一个,此解决方案将不起作用 用正确答案更新了代码。只需添加即可获得which 条件中的第一个值。【参考方案5】:

我们可以使用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)

【讨论】:

有类似想法:idx &lt;- Position(function(x) x == 5, use); replace(x &lt;- match(use, 5), is.na(x) &amp; seq_len(length(x)) &gt; idx, 0)【参考方案6】:

这是另一种变体。如果向量中没有 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,而输入有两个5。你不认为你也应该复制它吗?【参考方案7】:

你应该试试:

`is.na<-`(match(use, 5, 0), seq(match(5, use) - 1))
 [1] NA NA NA NA  1  0  0  0  0  1  0

【讨论】:

【参考方案8】:

这是一个基本的 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

【讨论】:

我想说,如果向量没有任何目标数字(在本例中为数字 5),这是唯一有效的解决方案。其他解决方案不会替换中的任何数字如果目标号码不存在。 @L.Rattis 很高兴听到这个消息。希望我的回答对你有帮助【参考方案9】:

奇怪的子集:

c(NA[!cumsum(use == 5)], +(use[!!cumsum(use == 5)] == 5))
#[1] NA NA NA NA  1  0  0  0  0  1  0

【讨论】:

以上是关于更改条件以替换向量中的元素的主要内容,如果未能解决你的问题,请参考以下文章

通过 C++ 中的外部函数更改存储在另一个对象的向量中的对象中元素的值

R:来自具有 2 个可能条件 (+/-) 的元素向量的所有可能组合

numpy 元素的条件格式

闪亮的小部件,以更改向量中的元素的顺序

使用条件语句替换 pandas DataFrame 中的条目

在R中添加带有条件的向量元素