我有这些数字:
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
?
答案 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 -> 6
,1 -> 7
和2 -> 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]