【问题标题】:Replacing 0 in particular order using nested if and for loop in r在 r 中使用嵌套的 if 和 for 循环以特定顺序替换 0
【发布时间】:2017-11-29 12:12:03
【问题描述】:

我正在尝试通过在 r 中使用 for 和嵌套 if 来解决以下问题: 我的可用价格数据是: 测试2

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)

问题: 用第一次出现的值替换第一次出现价格之前的 0,然后用第一次出现的值替换第一次出现之后的 0,直到第二次出现价格,依此类推。价格最后一次出现后的 0 应替换为最后一次出现的值。

我使用了以下代码:

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
}

在此之后我得到以下结果:

[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

这正是我想要的。 问题是我使用上面的代码得到错误:

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

我做错了什么吗? 对于上述问题,还有其他使用 apply 系列的替代方法吗?

【问题讨论】:

  • 请使用 dput() 共享您的数据

标签: r for-loop if-statement vector apply


【解决方案1】:

您可以使用包zoo 中的na.locf 来执行此操作。基本上,您首先想用 NA 替换所有零。然后使用na.locf 转发和na.rm = FALSE 保持领先的NA。然后使用 na.locf 向后使用 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

【讨论】:

  • na.locf(with(priceposition2, ifelse(priceposition2 == 0, NA_real_, priceposition2)), fromLast = TRUE)
【解决方案2】:

Reduce in base R 非常适合您所追求的(v 是您的向量):

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

【讨论】:

    【解决方案3】:

    您可以在整个向量的索引中使用findInterval,使用高于零值的位置作为区间边界。然后,您使用这些区间数来交换正确的高于零的值(第一个用于两个区间)。

    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]
    

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 2021-08-09
      • 2020-03-06
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多