【问题标题】:Generate new column in R, keep value if it meets a condition, else use the previous column在R中生成新列,如果满足条件则保留值,否则使用上一列
【发布时间】:2021-02-09 09:27:14
【问题描述】:

我正在使用 R 生成两个单独的长度为 20 的列向量,我想向它们添加 150 个额外的列向量,并根据先前列中的值保留新值。我使用以下代码启动两个列向量:

n <- 20
set.seed(4)
x0 <- runif(n = n, min = -9, max = 9)
set.seed(16)
y0 <- runif(n = n, min = -9, max = 9)

这给了我每个向量的第一列。然后,我根据这些值生成第二列。但是,如果它们满足某些条件,我只想保留每行的新值。如果它们不满足条件,我希望将新列值替换为旧列值。下面的代码是生成新列,分析其值,保留新值或用旧值替换,然后重复150次迭代:

iter <- 150
for(j in 1:iter){
  St <- runif(n = n, min = 0, max = 2)
  dt <- runif(n = n, min = 0, max = 2*pi)
  dx <- cos(dt)
  dy <- sin(dt)
  xm <- St*dx
  ym <- St*dy
  x0 <- cbind(x0, xm)
  y0 <- cbind(y0, ym)
  xall <- t(apply(x0, 1, cumsum))
  yall <- t(apply(y0, 1, cumsum))
  for(i in 1:n){
    if(xall[i,j+1]<=3 & xall[i,j+1]>=-3 & yall[i,j+1]<=3 & yall[i,j+1]>=-3){
      xall[i,j+1] <- xall[i,j+1]
      yall[i,j+1] <- yall[i,j+1]
    }
    else if(xall[i,j]>3 | xall[i,j]<(-3) | yall[i,j]>3 | yall[i,j]<(-3)){
      xall[i,j+1] <- xall[i,j+1]
      yall[i,j+1] <- yall[i,j+1]
    }
    else{
      xall[i,j+1] <- xall[i,j]
      yall[i,j+1] <- yall[i,j]
    }
  }
}

“xall”和“yall”数组不断地向它们添加列,一一地进行 150 次迭代。每次迭代并添加新列后,应遵循以下规则:

  • 如果第 j+1 列中的两个新值都在 -3 和 3 之间,则无论如何取新值,即使第 j 列中的当前值也在范围内
  • 如果第 j 列中至少有一个当前值超出此范围,则无论如何都取第 j+1 列中的新值
  • 如果第j列的当前值在范围内,但第j+1列的新值不在范围内,则用第j列的当前值替换第j+1列的新值
  • 完成列值比较,生成新列,然后再次检查规则

我将在此处给出我的代码的示例输出,该代码目前无法按需要运行:

> xall[3,10:14]
      x10       x11       x12       x13       x14 
-3.657078 -2.558799 -2.790860 -2.797736 -3.372856 

> yall[3,10:14]
      y10       y11       y12       y13       y14  
-1.938531 -2.991856 -2.597014 -2.694228 -3.363116 

从 x10 和 y10 开始。其中至少有一个超出范围 [-3,3],因此它们应该接受第 11 列的新列值(按预期工作)。在第 11 列中,x11 和 y11 都在范围内,但下一列 x12 和 y12 也在范围内,因此它们应该接受新值(按预期工作)。跳转到 x13 和 y13,两者都在范围内,但下一个值至少有一个不在范围内。所以 x14 和 y14 应该复制以前的值(不按预期工作)。目标是为 x14 和 y14 获得类似的东西:

> xall[3,10:14]
      x10       x11       x12       x13       x14 
-3.657078 -2.558799 -2.790860 -2.797736 -2.797736

> yall[3,10:14]
      y10       y11       y12       y13       y14  
-1.938531 -2.991856 -2.597014 -2.694228 -2.694228 

这本质上是一个随机游走问题。有没有办法让每个点达到​​[-3,3]之间的目标,然后到达后不离开?

【问题讨论】:

    标签: r arrays if-statement nested-loops calculated-columns


    【解决方案1】:

    我认为问题在于您的循环在索引 j(1 到 150)上运行并替换了 j+1 列中的值。因此,这些值可能会在循环的下一次迭代中被替换(取决于新的 j 和 j+1 值)。

    分离列的创建和检查/替换值是否得到您想要的?如果两个值 (x/y) 在同一列中的范围内(我假设这是您想要的),这会使值保持在范围内。

    为了稍微简化一下,我使用逻辑向量而不是行上的循环来进行值的条件替换。

    n <- 20
    set.seed(4)
    x0 <- runif(n = n, min = -9, max = 9)
    set.seed(16)
    y0 <- runif(n = n, min = -9, max = 9)
    
    iter <- 150
    
    for(j in 1:iter){
      St <- runif(n = n, min = 0, max = 2)
      dt <- runif(n = n, min = 0, max = 2*pi)
      dx <- cos(dt)
      dy <- sin(dt)
      xm <- St*dx
      ym <- St*dy
      x0 <- cbind(x0, xm)
      y0 <- cbind(y0, ym)
    }
    
    xall <- t(apply(x0, 1, cumsum))
    yall <- t(apply(y0, 1, cumsum))
    
    #function to check if values are in target range
    chk <- function(x) {x <= 3 & x >= -3}
    
    for(icol in 1:iter) {
      
      #condition1: values in column icol+1 between -3 and 3
      idx1 <- chk(xall[,icol+1]) &  chk(yall[,icol+1])
    
      #condition2: values in column icol between -3 and 3
      idx2 <- chk(xall[,icol]) &  chk(yall[,icol])
    
      #replace values in icol+1 with icol if condition 2 but not condition 1
      idx3 = !idx1 & idx2
      
      xall[idx3,icol+1] <- xall[idx3,icol]
      yall[idx3,icol+1] <- yall[idx3,icol]
      
    }
    
    xall[3,10:14]
           xm        xm        xm        xm        xm 
    -3.657078 -2.558799 -2.790860 -2.797736 -2.797736 
    
    yall[3,10:14]
           ym        ym        ym        ym        ym 
    -1.938531 -2.991856 -2.597014 -2.694228 -2.694228 
    

    【讨论】:

      猜你喜欢
      • 2020-08-18
      • 1970-01-01
      • 2018-12-13
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 1970-01-01
      相关资源
      最近更新 更多