更改条件以替换向量中的元素
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 <- Position(function(x) x == 5, use); replace(x <- match(use, 5), is.na(x) & seq_len(length(x)) > 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 个可能条件 (+/-) 的元素向量的所有可能组合