【问题标题】:Filter vector of 1s and -1s in RR中1s和-1s的过滤向量
【发布时间】:2014-12-09 14:36:47
【问题描述】:

我想对以下向量应用几个过滤器:

v <-c(1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1-1,-1,-1,-1,-1,1,1,1,-1,-1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1-1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,-1,1,1,1,1,1-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1-1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1-1,1,1,1)

我想应用的过滤器应该删除 -1 中的 1,反之亦然。过滤器应适用于 3、4、5 和 6 个元素,如下所示:

(-1,1,-1) 到 (-1,-1,-1)

(1,-1,1) 到 (1,1,1)

(-1, 1, 1, -1) 到 (-1, -1, -1, -1)

(1,-1,-1, 1) 到 (1, 1, 1, 1)

(-1, 1, 1, 1, -1) 到 (-1, -1, -1, -1, -1)

(1, -1, -1, -1, 1) 到 (1, 1, 1, 1, 1)

(-1, 1, 1, 1, 1, -1) 到 (-1, -1, -1, -1, -1, -1)

(1, -1, -1, -1, -1, 1) 到 (1, 1, 1, 1, 1, 1)

我首先使用了 for 循环,然后尝试使用 paste 和 gsub 对循环进行矢量化(请参阅下面的完整示例)

但是,矢量化版本不会产生与 for 循环相同的结果(因为它不考虑在下一步骤中发生的更改)

是否有该代码的矢量化版本实际上与 for 循环具有相同的效果?


使用for-loop vs paste和gsub的两个完整示例:

v <-c(1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1-1,-1,-1,-1,-1,1,1,1,-1,-1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1-1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,-1,1,1,1,1,1-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1-1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1-1,1,1,1)
t1 <- v
t2 <- v

-1 1 -1 到 -1 -1 -1

for (i in 2:(length(t1)-1)) {
        if (t1[i-1]==-1 & t1[i+1]==-1 & t1[i]==1){
                t1[i] <- -1   
        } 
}

1 -1 1 到 1 1 1

for (i in 2:(length(t1)-1)) {
        if (t1[i-1]==1 & t1[i+1]==1 & t1[i]==-1){
                t1[i] <- 1
        } 
}

-1 1 1 -1 到 -1 -1 -1 -1

for (i in 3:(length(t1)-1)) {
        if (t1[i-2]==-1 & t1[i+1]==-1 & t1[i]==1 & t1[i-1] ==1) {
                t1[i]   <- -1
                t1[i-1] <- -1
        }
}

1 -1 -1 1 到 1 1 1 1

for (i in 3:(length(t1)-1)) {
        if (t1[i-2]==1 & t1[i+1]==1 & t1[i]==-1 & t1[i-1] ==-1) {
                t1[i]   <- 1
                t1[i-1] <- 1
        }
}

-1 1 1 1 -1 到 -1 -1 -1 -1 -1

for (i in 4:(length(t1)-1)) {
        if (t1[i-3]==-1 & t1[i+1]==-1 & t1[i-2]==1 & t1[i-1] ==1 & t1[i] ==1) {
                t1[i-2]   <- -1
                t1[i-1]   <- -1
                t1[i]     <- -1
        }
}

1 -1 -1 -1 1 到 1 1 1 1 1

for (i in 4:(length(t1)-1)) {
        if (t1[i-3]==1 & t1[i+1]==1 & t1[i-2]==-1 & t1[i-1] ==-1 & t1[i] ==-1) {
                t1[i-2]   <- 1
                t1[i-1]   <- 1
                t1[i]     <- 1
        }
}

-1 1 1 1 1 -1 到 -1 -1 -1 -1 -1 -1

for (i in 5:(length(t1)-1)) {
        if (t1[i-4]==-1 & t1[i+1]==-1 & t1[i-3]==1 & t1[i-2]==1 & t1[i-1] ==1 & t1[i] ==1) {
                t1[i-3]   <- -1
                t1[i-2]   <- -1
                t1[i-1]   <- -1
                t1[i]     <- -1
        }
}

1 -1 -1 -1 -1 1 到 1 1 1 1 1 1

for (i in 5:(length(t1)-1)) {
        if (t1[i-4]==1 & t1[i+1]==1 & t1[i-3]==-1 & t1[i-2]==-1 & t1[i-1] ==-1 & t1[i] ==-1) {
                t1[i-3]   <- 1
                t1[i-2]   <- 1
                t1[i-1]   <- 1
                t1[i]     <- 1
        }
}

现在是矢量化 gsub 版本:

t2 <- paste(v, collapse="")

-1 1 -1 到 -1 -1 -1

t2 <- gsub("-11-1", "-1-1-1", t2)

1 -1 1 到 1 1 1

t2 <- gsub("1-11", "111", t2)

-1 1 1 -1 到 -1 -1 -1 -1

t2 <- gsub("-111-1", "-1-1-1-1", t2)

1 -1 -1 1 到 1 1 1 1

t2 <- gsub("1-1-11", "1111", t2)

-1 1 1 1 -1 到 -1 -1 -1 -1 -1

t2 <- gsub("-1111-1", "-1-1-1-1-1", t2)

1 -1 -1 -1 1 到 1 1 1 1 1

t2 <- gsub("1-1-1-11", "11111", t2)

-1 1 1 1 1 -1 到 -1 -1 -1 -1 -1 -1

t2 <- gsub("-11111-1", "-1-1-1-1-1-1", t2)

1 -1 -1 -1 -1 1 到 1 1 1 1 1 1

t2 <- gsub("1-1-1-1-11", "111111", t2)

t2 <-as.integer(strsplit(t2, "(?<=\\d)", perl = TRUE)[[1]])
all.equal(t1, t2)

[1] "平均相对差:2"

【问题讨论】:

  • 例如t[t==1] &lt;- -1。顺便说一句,t 不是一个好的变量名。试试?t
  • 您的循环正在修改您的数据。他们可能没有完全按照您的预期行事......
  • 您能否添加一个示例,其中 for 循环与 paste 的矢量化解决方案不匹配?对于您提供的向量,第一个 for 循环的输出与向量化解决方案完全匹配。因此,您尚未提供可重现的问题示例。
  • Simon:我已经将其更改为 v、t1 和 t2 James:这就是他的想法,在以下循环步骤中使用一组元素中的更改 josilber:你是对的,我还在在这件事上努力养成良好的习惯。我在问题末尾添加了一个完整的示例

标签: r for-loop vectorization


【解决方案1】:

您可以轻松地将其翻译成 Rcpp:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector myfilter(IntegerVector x) {
  for (int i = 1; i < (x.size() - 1); i++) {
    if (x(i-1) == -1 && x(i+1) == -1 && x(i) == 1) {
      x(i) = -1;
    }    
  }

  for (int i = 2; i < (x.size() - 1); i++) {
    if (x(i-2) == -1 && x(i-1) == 1 && x(i+1) == -1 && x(i) == 1) {
      x(i) = -1;
      x(i-1) = -1;
    }    
  }  
   return x;
}

在 R 中测试它:

t1 <- myfilter(t)

for (i in 2:(length(t)-1)) {
  if (t[i-1]==-1 & t[i+1]==-1 & t[i]==1){
    t[i] <- -1   
  } 
}

for (i in 3:(length(t)-1)) {
  if (t[i-2]==-1 & t[i+1]==-1 & t[i]==1 & t[i-1] ==1) {
    t[i]   <- -1
    t[i-1] <- -1
  }
}

all.equal(t, t1)
#[1] TRUE

【讨论】:

  • 谢谢罗兰!我花了一段时间才明白您编写的代码是用 C++ 编写的,这实际上是一个绝妙的主意!我正在尝试应用代码,但首先需要了解 Rcpp 和 C++ 基础知识(这对我的项目有很大帮助)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 2014-08-08
  • 1970-01-01
  • 2016-10-13
  • 2016-01-24
  • 2020-07-01
  • 2011-09-12
相关资源
最近更新 更多