简体   繁体   English

使用r中的嵌套if和for循环以特定顺序替换0

[英]Replacing 0 in particular order using nested if and for loop in r

i'm trying to solve the following by using for and nested if in r: my data for price available is: test2 我正在尝试通过使用for和嵌套在r中来解决以下问题:我的可用价格数据是:test2

test2 <- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 399, 0, 0, 399, 0, 0, 0, 0, 399, 0, 0, 0, 0, 429, 0, 429, 
0, 0, 0, 499, 0, 429, 0, 0, 0, 0, 0, 529, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0)

the problem: to replace 0 before the 1st occurrence of price with value of the 1st occurrence, then replace 0 after 1st occurrence with the value of 1st occurrence until 2nd occurrence of price and so on. 问题:将第一次出现价格之前的0替换为第一次出现的值,然后将第一次出现之后的0替换为第一次出现的值,直到第二次出现价格,依此类推。 The 0 after last occurrence of price should be replaced with the value of last occurrence. 最后一次出现的价格后的0应该替换为最后一次出现的值。

I have used the following code: 我使用了以下代码:

priceposition2 <- which(test2>0)
for(i in 1:length(priceposition2)){
for(m in 1:length(test2)){
  if (m <= priceposition2[1]){
test2[m] <- test2[priceposition2[1]]
} else if (m > priceposition2[1]){
  if (m> priceposition2[i] && m < priceposition2[i+1]){
    test2[m] <- test2[priceposition2[i]]

  }else if(m> priceposition2[length(priceposition2)]){
    test2[m] <- test2[priceposition2[length(priceposition2)]]
  }

}
m=m+1
}
 i=i+1
}

I get the following result after this: 在此之后,我得到以下结果:

[1] 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 
399 399 399 399 399
[24] 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 
399 399 399 399 399
[47] 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 
399 399 399 399 399 399
[70] 399 399 399 399 399 399 399 399 429 429 429 429 429 429 499 499 429 429 
429 429 429 429 529
[93] 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 
529 529 529 529 529
[116] 529 529 529 529 529 529 529 529 529 529 529 529 529 529

which is exactly what i want. 这正是我想要的。 The problem is i get error by using the above code: 问题是我通过使用上面的代码得到错误:

Error in if (m > priceposition2[i] && m < priceposition2[i + 1]) { : 
 missing value where TRUE/FALSE needed

Is there something that i'm doing wrong? 我做错了什么吗? Also is there an alternative using apply family for the above problem? 还有解决上述问题的替代方法吗?

You could use na.locf from package zoo to do this. 您可以使用来自zoo软件包的na.locf来执行此操作。 Basically, you first want to replace all zeros with NA. 基本上,您首先要用NA替换所有零。 Then use na.locf forwards with na.rm = FALSE to keep leading NAs. 然后使用na.locf na.rm = FALSE na.locf转发来保持领先的NA。 And then use na.locf backwards with fromLast=TRUE to change the leading NAs to the first value. 然后使用na.locf fromLast=TRUE向后使用fromLast=TRUE将前导NA更改为第一个值。

priceposition2<-c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,399,0,0,399,0,
0,0,0,399,0,0,0,0,429,0,429,0,0,0,499,0,429,0,
0,0,0,0,529,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) 

library(zoo)
priceposition2[priceposition2==0] <- NA
na.locf(na.locf(priceposition2,na.rm = FALSE),fromLast=TRUE)

  [1] 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399
 [33] 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399 399
 [65] 399 399 399 399 399 399 399 399 399 399 399 399 399 429 429 429 429 429 429 499 499 429 429 429 429 429 429 529 529 529 529 529
 [97] 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529 529
[129] 529

Reduce基数R非常适合您所追求的目标( v是您的向量):

Reduce(function(x,y) ifelse(y==0, x, y), v, accumulate=TRUE, init = v[v>0][1])[-1]

You can use findInterval across the indices of the entire vector, using the locations of the above-zero values as the interval boundaries. 您可以使用零值以上的位置作为间隔边界,在整个矢量的索引中使用findInterval Then you use those interval numbers to swap in the correct above-zero values (with the first one used for two intervals). 然后,您可以使用这些间隔号交换正确的零以上值(第一个用于两个间隔)。

above_zero <- which(test2 > 0)
carryover_from <- findInterval(seq_along(test2), c(0, above_zero))
carryover_values <- c(test2[above_zero[1]], test2[above_zero])
test2 <- carryover_values[carryover_from]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM