生成一个带有重复间隔的数字序列

25

我正在尝试创建六位数字的序列,但间隔为144个数字。

比如这个例子

c(1:6, 144:149, 288:293)

1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

我怎样才能自动生成这样的一个序列?

seq 

或者使用另一个函数?

6个回答

27

我发现在这种情况下使用sequence函数是有帮助的。如果你的数据结构像这样:

(info <- data.frame(start=c(1, 144, 288), len=c(6, 6, 6)))
#   start len
# 1     1   6
# 2   144   6
# 3   288   6

你可以用一行代码来完成这个操作:

sequence(info$len) + rep(info$start-1, info$len)
#  [1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

请注意,即使您要合并的序列长度不同,此解决方案仍然有效。


是的,考虑到 OP 示例中的异常间隔,像那样显式地存储结构可能是一个不错的主意。 - Frank
1
? 页面中可以看到,"请注意 sequence <- function(nvec) unlist(lapply(nvec, seq_len)) 主要是为了纪念 R 早期历史而存在的。" 类似于 Frank 的回答。 - Carl Witthoft
@josilber - 我还需要手动填写c(1, 144, 288)吗?如果我想要10个序列或100个6位数的序列,该怎么办?你有什么解决方案吗?谢谢。 - giac
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - josliber
1
自从 R >= 4.0.0 版本以来,sequence 函数现在有一个内置参数 from,这对于编程非常有帮助!请参见此处 - Maël

7

以下是一种方法:

unlist(lapply(c(0L,(1:2)*144L-1L),`+`,seq_len(6)))
# or...
unlist(lapply(c(1L,(1:2)*144L),function(x)seq(x,x+5)))

这是我更喜欢的一种方式:

rep(c(0L,(1:2)*144L-1L),each=6) + seq_len(6)

概括来说...

rlen  <- 6L
rgap  <- 144L
rnum  <- 3L

starters <- c(0L,seq_len(rnum-1L)*rgap-1L)

rep(starters, each=rlen) + seq_len(rlen)
# or...
unlist(lapply(starters+1L,function(x)seq(x,x+rlen-1L)))

1
我觉得这个问题应该有更优雅的解决方案。 - Frank
unlist(lapply(...)) 可以替换为 sapply。 - hedgedandlevered
这是我的解决方案,但我不知道如何调整它以适应混合间隔 (1:293)[c(rep(T,6L), rep(F, 137L))] - Pierre L
2
@MikeWise 是的,他们说seq_len稍微快一点,但我觉得在这个应用程序中并不重要。只是习惯问题。另外,为了实现“泛化”,我必须编写\:`(1,rlen)`,这有点尴尬。 - Frank
2
@giacomoV 没有必要着急接受。我对我的答案并不十分满意,所以我宁愿看到你把问题保持开放一两天,看看是否能找到更好的答案。 - Frank
显示剩余7条评论

5
这也可以使用seqseq.int来完成。
x = c(1, 144, 288)
c(sapply(x, function(y) seq.int(y, length.out = 6)))

#[1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

正如评论中@Frank所提到的,这里有另一种方法可以使用@josilber的数据结构来实现这一目的(当不同时间间隔需要不同的序列长度时,这非常有用)

c(with(info, mapply(seq.int, start, length.out=len)))

#[1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

1
是的,这很好。但我觉得奇怪的是,即使我切换到 x = c(1L, 144L, 288L),我仍然无法获得整数结果。我认为这是 seq 处理 length.out 的缺陷... 幸运的是,seq.int 似乎做了“正确”的事情。 - Frank
2
是的,我知道。seq(1L,length.out=6)的结果应该是一个整数向量,这是我的观点。我批评的是函数的工作方式,而不是你的答案(在我看来,这似乎是迄今为止最好的答案)。如果x是整数并且使用seq.int代替seq,那么你的答案会“更好”(在我看来),因此最终结果是一个整数向量(就像OP的示例)。 - Frank
3
很抱歉,seq/seq.int函数在 length.out 参数上不支持向量化。这意味着使用 mapply 而不是 sapply 是解决问题的方法。在使用 josilber 提供的数据结构时,可以使用 c(with(info, mapply(seq.int, start, length.out=len))) - Frank
@josilber 哦,我以为seq在其他参数中进行了向量化处理,但我看到你是对的。无论如何,在这里我仍然更喜欢使用mapply,直接构建序列而不是算术构建。我可以阅读那行代码并猜测它正在做什么。 - Frank
1
@Frank 看起来只是个人偏好问题 :) - josliber
显示剩余2条评论

3
R >= 4.0.0版本开始,您现在可以使用sequence在一行内完成此操作:
sequence(c(6,6,6), from = c(1,144,288))
[1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

第一个参数nvec是每个序列的长度;第二个参数from是每个序列的起始点。

作为一个函数,n表示您想要的区间数:

f <- function(n) sequence(rep(6,n), from = c(1,144*1:(n-1)))
f(3)
[1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

1
不错 - 这应该是被采纳的答案。 - josliber

0

我正在使用 R 3.3.2 和 OSX 10.9.4。

我尝试过:

a<-c()  # stores expected sequence
f<-288  # starting number of final sub-sequence
it<-144 # interval
for (d in seq(0,f,by=it))
{
    if (d==0)
    {
        d=1
    }
    a<-c(a, seq(d,d+5))
    print(d)
}
print(a)

并且期望的序列存储在a中。

[1] 1 2 3 4 5 6 144 145 146 147 148 149 288 289 290 291 292 293

再试一次:

a<-c()  # stores expected sequence
it<-144 # interval
lo<-4   # number of sub-sequences
for (d in seq(0,by=it, length.out = lo))
{
    if (d==0)
    {
        d=1
    }
    a<-c(a, seq(d,d+5))
    print(d)
}
print(a)

结果如下:

[1] 1 2 3 4 5 6 144 145 146 147 148 149 288 289 290 291 292 293 432 433 434 435 436 437


0
我使用了 cumsum 函数来解决这个问题。
seq_n <- 3 # number of sequences
rep(1:6, seq_n) + rep(c(0, cumsum(rep(144, seq_n-1))-1), each = 6)
# [1]   1   2   3   4   5   6 144 145 146 147 148 149 288 289 290 291 292 293

无需像@josilber的解决方案那样计算序列的起始值,但序列的长度必须保持不变。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接