这是我的时间段范围:
start_day = as.Date('1974-01-01', format = '%Y-%m-%d')
end_day = as.Date('2014-12-21', format = '%Y-%m-%d')
df = as.data.frame(seq(from = start_day, to = end_day, by = 'day'))
colnames(df) = 'date'
我需要创建10,000个data.frames,每个都有不同的假日年365天。这意味着10,000个data.frames中的每一个都需要具有不同的年初和年终。
总共df
有14,965天,除以365天= 41年。换句话说,df
需要按照 10,000次不同分组41年(每天365天)。
每年的开始必须是随机的,所以它可以是1974-10-03,1974-08-30,19991-01-03等......并且最后的剩余日期df
需要与起始人一起回收。
分组的假年份需要出现在data.frames的第3列中。
我会把所有data.frames放到一个列表中,但我不知道如何创建生成10,000个不同年份开始日期的函数,然后将每个data.frame与365天窗口分组41次。
任何人都可以帮助我吗?
@gringer给出了一个很好的答案,但它只解决了90%的问题:dates.df <- data.frame(replicate(10000, seq(sample(df$date, 1),
length.out=365, by="day"),
simplify=FALSE))
colnames(dates.df) <- 1:10000
我需要的是10,000列,其中14,965行是根据df
的日期制作的,当到达df
时,需要最终回收。
我尝试更改length.out = 14965
,但R不回收日期。
另一个选项可能是更改length.out = 1并最终通过维护相同的顺序为每列添加剩余的df
行:
dates.df <- data.frame(replicate(10000, seq(sample(df$date, 1),
length.out=1, by="day"),
simplify=FALSE))
colnames(dates.df) <- 1:10000
如何将剩余的df
行添加到每个col?
答案 0 :(得分:3)
如果seq
参数未指定,to
方法也有效,因此它可用于生成从特定日期开始的特定天数:
> seq(from=df$date[20], length.out=10, by="day")
[1] "1974-01-20" "1974-01-21" "1974-01-22" "1974-01-23" "1974-01-24"
[6] "1974-01-25" "1974-01-26" "1974-01-27" "1974-01-28" "1974-01-29"
与replicate
和sample
结合使用时,我认为这会在列表中提供您想要的内容:
> replicate(2,seq(sample(df$date, 1), length.out=10, by="day"), simplify=FALSE)
[[1]]
[1] "1985-07-24" "1985-07-25" "1985-07-26" "1985-07-27" "1985-07-28"
[6] "1985-07-29" "1985-07-30" "1985-07-31" "1985-08-01" "1985-08-02"
[[2]]
[1] "2012-10-13" "2012-10-14" "2012-10-15" "2012-10-16" "2012-10-17"
[6] "2012-10-18" "2012-10-19" "2012-10-20" "2012-10-21" "2012-10-22"
没有simplify=FALSE
参数,它会产生一个整数数组(即R的日期内部表示),转换回日期有点棘手。执行此操作的一种稍微复杂的方法是生成日期输出,以便在未简化的data.frame
结果上使用replicate
。这是一个示例,它将生成一个10,000列的数据框,每列中包含365个日期(在我的计算机上生成大约需要5秒):
dates.df <- data.frame(replicate(10000, seq(sample(df$date, 1),
length.out=365, by="day"),
simplify=FALSE));
colnames(dates.df) <- 1:10000;
> dates.df[1:5,1:5];
1 2 3 4 5
1 1988-09-06 1996-05-30 1987-07-09 1974-01-15 1992-03-07
2 1988-09-07 1996-05-31 1987-07-10 1974-01-16 1992-03-08
3 1988-09-08 1996-06-01 1987-07-11 1974-01-17 1992-03-09
4 1988-09-09 1996-06-02 1987-07-12 1974-01-18 1992-03-10
5 1988-09-10 1996-06-03 1987-07-13 1974-01-19 1992-03-11
要使日期环绕工作,可以对原始数据框稍作修改,在最后粘贴自己的副本:
df <- as.data.frame(c(seq(from = start_day, to = end_day, by = 'day'),
seq(from = start_day, to = end_day, by = 'day')));
colnames(df) <- "date";
这对于下游更容易编码;替代方案是每个结果列的双seq
,其中包含用于处理边界情况的开始/结束和if
语句的附加计算。
现在,不是进行日期算术,而是从原始数据帧(算术已经完成)的结果列子集。从帧的前半部分中的一个日期开始,然后选择下一个14965值。我使用nrow(df)/2
代替更通用的代码:
dates.df <-
as.data.frame(lapply(sample.int(nrow(df)/2, 10000),
function(startPos){
df$date[startPos:(startPos+nrow(df)/2-1)];
}));
colnames(dates.df) <- 1:10000;
>dates.df[c(1:5,(nrow(dates.df)-5):nrow(dates.df)),1:5];
1 2 3 4 5
1 1988-10-21 1999-10-18 2009-04-06 2009-01-08 1988-12-28
2 1988-10-22 1999-10-19 2009-04-07 2009-01-09 1988-12-29
3 1988-10-23 1999-10-20 2009-04-08 2009-01-10 1988-12-30
4 1988-10-24 1999-10-21 2009-04-09 2009-01-11 1988-12-31
5 1988-10-25 1999-10-22 2009-04-10 2009-01-12 1989-01-01
14960 1988-10-15 1999-10-12 2009-03-31 2009-01-02 1988-12-22
14961 1988-10-16 1999-10-13 2009-04-01 2009-01-03 1988-12-23
14962 1988-10-17 1999-10-14 2009-04-02 2009-01-04 1988-12-24
14963 1988-10-18 1999-10-15 2009-04-03 2009-01-05 1988-12-25
14964 1988-10-19 1999-10-16 2009-04-04 2009-01-06 1988-12-26
14965 1988-10-20 1999-10-17 2009-04-05 2009-01-07 1988-12-27
这需要花费更少的时间,大概是因为日期值已被预先计算。
答案 1 :(得分:2)
试试这个,改为使用子集:
start_day = as.Date('1974-01-01', format = '%Y-%m-%d')
end_day = as.Date('2014-12-21', format = '%Y-%m-%d')
date_vec <- seq.Date(from=start_day, to=end_day, by="day")
现在,我创建了一个足够长的向量,以便稍后可以使用简单的子集:
date_vec2 <- rep(date_vec,2)
现在,为100个实例创建随机开始日期(将10000替换为您的应用程序):
random_starts <- sample(1:14965, 100)
现在,只需使用您想要的长度对date_vec2
进行子集化,即可创建日期列表:
dates <- lapply(random_starts, function(x) date_vec2[x:(x+14964)])
date_df <- data.frame(dates)
names(date_df) <- 1:100
date_df[1:5,1:5]
1 2 3 4 5
1 1997-05-05 2011-12-10 1978-11-11 1980-09-16 1989-07-24
2 1997-05-06 2011-12-11 1978-11-12 1980-09-17 1989-07-25
3 1997-05-07 2011-12-12 1978-11-13 1980-09-18 1989-07-26
4 1997-05-08 2011-12-13 1978-11-14 1980-09-19 1989-07-27
5 1997-05-09 2011-12-14 1978-11-15 1980-09-20 1989-07-28