【问题标题】:Extracting alternating sequence from vector in R从R中的向量中提取交替序列
【发布时间】:2016-05-22 21:05:21
【问题描述】:

我的数据如下所示:

A= c(0,0,0,-1,0,0,0,1,1,1,0,0,-1,0,0,-1,-1,1,1,1,-1,0,0,0,-1,0,0,-1,-1,1,1,0,0,0,0,1,-1)

目标是提取交替的 -1 和 1。我想创建一个函数,其中输入向量包含 0,1 和 -1。理想情况下,输出会吐出所有 0 并交替出现 -1 和 1。

例如,上面示例的期望输出是:

 B= c(0,0,0,-1,0,0,0,1,0,0,0,0,-1,0,0,0,0,1,0,0,-1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,-1)

A 中第 9 和第 10 个位置的两个 1 变为 0,因为我们只保留第一个 1 或 -1 出现。 A 的第 16 和第 17 位置的 -1 也因此变为 0。

谁有制作这样一个功能的好主意?

【问题讨论】:

  • 为什么这个问题被否决和 vtc?用一个例子很好地解释了。
  • 在我看来奇怪的值是位置 16。它从位置 15 的 0 切换到 -1 但被删除了。为什么?
  • 目标是只保持唯一的 1 和 -1 来振荡。第13个位置有-1,所以在观察到下一个1之前,所有的-1都变成0。

标签: r vector sequence


【解决方案1】:

识别非零值的位置:

w = which(A != 0)

对于每次运行的相似值,在A[w]中,取第一个的位置:

library(data.table)
wkeep = tapply(w, rleid(A[w]), FUN = function(x) x[1])

将所有其他值设置为零:

# following @alexis_laz's approach
B = numeric(length(A)) 
B[ wkeep ] = A[ wkeep ]

这样,您不必在循环中进行比较,我认为 R 的速度很慢。


rleid 来自 data.table。使用base R,您可以根据@alexis_laz 的建议制作wkeep

wkeep = w[c(TRUE, A[w][-1L] != A[w][-length(w)])]

或者写你自己的rleid,就像Josh's answer一样。

【讨论】:

  • 同样的方法:w = which(A != 0L); wkeep = w[c(TRUE, A[w][-1L] != A[w][-length(w)])]; ans = numeric(length(A)); ans[wkeep] = A[wkeep]; ans
  • @alexis_laz 现有的答案非常好。但我想说你的不同之处足以单独发布,特别是因为它只使用基本 R 函数(我发现它更容易理解)。
  • 谢谢@alexis_laz。我已经为wkeep 添加了您的方法,并用您的方法覆盖了我的第三步(用于制作ans)。
  • 感谢您的意见。我有一个非常大的数据,这很有帮助。
  • @jay2020 请注意,如果在您接受第一个答案后出现您喜欢的新答案,您可以更改您接受的答案。 (我通常在接受任何东西之前至少等待几个小时)
【解决方案2】:

这实际上只是 GWarius 伪代码的具体化。 (我已经有一个结构但逻辑失败了。)

last1 <- -A[which(A != 0)[1] ] # The opposite of the first non-zero item
for (i in seq_along(A) ){ 
          if( last1==1 &&  A[i]==-1  ){ last1 <- -1
          } else {if (last1 == -1 && A[i] == 1) { last1 <- 1
                 } else {A[i] <- 0}} }
 A
 [1]  0  0  0 -1  0  0  0  1  0  0  0  0 -1  0  0  0  0  1  0  0 -1  0  0
[24]  0  0  0  0  0  0  1  0  0  0  0  0  0 -1

> identical(A, B)
[1] TRUE

【讨论】:

  • 是的。我尝试使用 last1=0 并且失败了。我想您可以将其设置为 -A[which(A != 0)[1] ]
  • 谢谢。我已经使用 Warlus 的建议解决了它,所以我不得不选择 Warlus。但我真的很感谢你的时间。
  • 没问题。我在一些问题上花费了更多时间,但获得的赞成票更少。
【解决方案3】:

您必须滑动所有数组并使用标志变量检查之前是否找到 1 或 -1。 可能是伪代码算法:

while i < length(a):

   if flag == 1 && a[i]=-1:
      b[i]=a[i];
      flag = -1;
   else if flag == -1 && a[i] = 1:
      b[i]=a[i];
      flag = 1;
   else:
      b[i]=0;
   i++;
}//end of while

【讨论】:

  • 感谢您的建议
猜你喜欢
  • 2018-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 2019-05-12
  • 1970-01-01
  • 2019-04-18
  • 2015-10-02
相关资源
最近更新 更多