包裹减法

时间:2014-04-20 09:25:03

标签: r

我有这些数字:

login.day$wday
[1] 5 6 7 1 2 3 4

我希望将它们映射到:

login.day$wday
[1] 4 5 6 7 1 2 3

每个数字减去1,如果答案为0,则将其包裹回7个。这简直令人尴尬,但我无法理解。我的尝试一直给我零:

> (login.day$wday + 6) %% 7
[1] 4 5 6 0 1 2 3

首选R中的解决方案。是否可以使用模运算,还是必须使用if statement

4 个答案:

答案 0 :(得分:4)

在数学上等同于其他解决方案,并有一些解释。

(login.day$wday - 1 - 1) %% 7 + 1

问题在于,使用从1开始的数字很难进行模运算。

我们首先执行-1将所有内容向下移动1,因此我们有一个从零开始的数字[0,6]

然后我们减去1,因为这是我们开始尝试做的事情。

接下来,我们取模数,然后再添加1,将所有内容重新移回[1,7]范围。

答案 1 :(得分:2)

(login.day$wday + 5) %% 7 + 1

也许?

边界条件为7 -> 61 -> 72 -> 1

结果必须涉及%% 7,因为你正确地发现了。

由于这些边界条件中的最后一个导致1,因此我们需要在执行模数后加1,并将模数之前添加的数量减少1。

答案 2 :(得分:0)

我写了一个名为shift的愚蠢函数来执行此操作:

shift <- function(x = 1:10, n = 1) {
  if (n == 0) x <- x
  else x <- c(tail(x, -n), head(x, n))
  x
}

x <- c(5, 6, 7, 1, 2, 3, 4)

shift(x, -1)
# [1] 4 5 6 7 1 2 3

shift(x, -2)
# [1] 3 4 5 6 7 1 2

我想到的用途如下:

set.seed(1)
X <- sample(7, 20, TRUE)
X
#  [1] 2 3 5 7 2 7 7 5 5 1 2 2 5 3 6 4 6 7 3 6

shift(sort(unique(X)), -1)[X]
#  [1] 1 2 4 6 1 6 6 4 4 7 1 1 4 2 5 3 5 6 2 5

答案 3 :(得分:0)

我喜欢@ merlin2011的解决方案,但只是在这里添加选项是查找表方法:

c(7, 1:6)[login.day$wday]