使用两个数据框列应用 seq.Date
Apply seq.Date using two dataframe columns
我尝试使用来自
Expanding a sequence in a data frame
到我的数据框,但我没有尝试任何工作。
示例数据
library(dplyr)
p1 <- c(1:5)
p2 <- as.Date(c("2013-01-01","2013-01-22","2014-02-01","2014-05-12","2015-02-22"))
p3 <- as.Date(c("2013-01-11","2013-01-30","2014-02-20","2014-05-22","2015-02-28"))
p4 <- c(11,9,20,11,7)
df2 <- data_frame(p1,p2,p3,p4)
names(df2) <- c("ID", "StartDate", "EndDate", "NoDays")
df2
想要的结果
ID datelist NoDays
1 2013-01-01 1
1 2013-01-02 1
1 2013-01-03 1
etc..
1 2013-01-10 1
1 2013-01-11 1
2 2013-01-22 1
2 2013-01-23 1
etc.
2 2013-01-28 1
2 2013-01-29 1
2 2013-01-30 1
这里有三个代码试验——所有这些我都尝试了很多变体(例如 apply 系列的许多成员),但都失败了(即给出不同的错误消息):
代码示例 1
datelist <- seq.Date(from = df2$StartDate, to=df2$StartDate, by="days")
代码示例 2
datelist <- seq.Date(from = df2$StartDate, by="days", length.out = df2$NoDays)
代码示例 2
datelist <- apply(df2, 1, seq.Date(from = df2$StartDate, to=df2$StartDate, by="days"))
你的问题是你给 seq.Date
一个向量,它的唯一值是 from
或 to
.
根据与您的申请调用相同的想法,它应该是:
apply(df2,1,function(x) { seq.Date( as.Date(x['StartDate']), as.Date(x['EndDate']), by='days') } )
这会为您提供一个包含每个行序列的列表:
[[1]]
[1] "2013-01-01" "2013-01-02" "2013-01-03" "2013-01-04" "2013-01-05" "2013-01-06" "2013-01-07" "2013-01-08" "2013-01-09"
[10] "2013-01-10" "2013-01-11"
[[2]]
[1] "2013-01-22" "2013-01-23" "2013-01-24" "2013-01-25" "2013-01-26" "2013-01-27" "2013-01-28" "2013-01-29" "2013-01-30"
[[3]]
[1] "2014-02-01" "2014-02-02" "2014-02-03" "2014-02-04" "2014-02-05" "2014-02-06" "2014-02-07" "2014-02-08" "2014-02-09"
[10] "2014-02-10" "2014-02-11" "2014-02-12" "2014-02-13" "2014-02-14" "2014-02-15" "2014-02-16" "2014-02-17" "2014-02-18"
[19] "2014-02-19" "2014-02-20"
[[4]]
[1] "2014-05-12" "2014-05-13" "2014-05-14" "2014-05-15" "2014-05-16" "2014-05-17" "2014-05-18" "2014-05-19" "2014-05-20"
[10] "2014-05-21" "2014-05-22"
[[5]]
[1] "2015-02-22" "2015-02-23" "2015-02-24" "2015-02-25" "2015-02-26" "2015-02-27" "2015-02-28"
为了获得您想要的输出,我们也应该 return id 和 NoDays 列。
在 base R 中我会这样做:
getDfForDates <- function(row) {
dseq <- seq.Date( as.Date(row['StartDate']), as.Date(row['EndDate']), by='days')
data.frame( ID=row['ID'], datelist=dseq, NoDays=1)
}
rbindlist(
apply(df2,1,function(x) {
getDfForDates(x)
} )
)
另一个使用 data.table
包的解决方案是:
setDT(df2)
df2[, list(datelist=seq.Date( StartDate, EndDate, by='days'), NoDays=1), by=ID]
如果我没有遗漏一点,两者都会给出预期的结果。
我会看看我是否可以制作一个正确的 dplyr 答案,因为你似乎正在使用这个包。 在寻找 dplyr 示例时终于找到了一个骗子,投票关闭。
我们可以使用 data.table
轻松做到这一点。将'data.frame'转换为'data.table'(setDT(df2)
,如果'ID'唯一,则按'ID'分组,得到seq
=27=] 至 'EndDate' by
'ID'.
library(data.table)
res <- setDT(df2)[,list(datelist=seq(StartDate, EndDate, by='1 day'),
NoDays = 1) , by = ID]
head(res)
# ID datelist NoDays
#1: 1 2013-01-01 1
#2: 1 2013-01-02 1
#3: 1 2013-01-03 1
#4: 1 2013-01-04 1
#5: 1 2013-01-05 1
#6: 1 2013-01-06 1
如果我们需要在 dplyr
中执行此操作,我们可能需要 do
,因为 mutate
不支持此类操作
library(dplyr)
df2 %>%
rowwise() %>%
do(data.frame(ID= .$ID, datelist = seq(.$StartDate,
.$EndDate, by = '1 day'), NoDays= 1))
我尝试使用来自 Expanding a sequence in a data frame 到我的数据框,但我没有尝试任何工作。
示例数据
library(dplyr)
p1 <- c(1:5)
p2 <- as.Date(c("2013-01-01","2013-01-22","2014-02-01","2014-05-12","2015-02-22"))
p3 <- as.Date(c("2013-01-11","2013-01-30","2014-02-20","2014-05-22","2015-02-28"))
p4 <- c(11,9,20,11,7)
df2 <- data_frame(p1,p2,p3,p4)
names(df2) <- c("ID", "StartDate", "EndDate", "NoDays")
df2
想要的结果
ID datelist NoDays
1 2013-01-01 1
1 2013-01-02 1
1 2013-01-03 1
etc..
1 2013-01-10 1
1 2013-01-11 1
2 2013-01-22 1
2 2013-01-23 1
etc.
2 2013-01-28 1
2 2013-01-29 1
2 2013-01-30 1
这里有三个代码试验——所有这些我都尝试了很多变体(例如 apply 系列的许多成员),但都失败了(即给出不同的错误消息):
代码示例 1
datelist <- seq.Date(from = df2$StartDate, to=df2$StartDate, by="days")
代码示例 2
datelist <- seq.Date(from = df2$StartDate, by="days", length.out = df2$NoDays)
代码示例 2
datelist <- apply(df2, 1, seq.Date(from = df2$StartDate, to=df2$StartDate, by="days"))
你的问题是你给 seq.Date
一个向量,它的唯一值是 from
或 to
.
根据与您的申请调用相同的想法,它应该是:
apply(df2,1,function(x) { seq.Date( as.Date(x['StartDate']), as.Date(x['EndDate']), by='days') } )
这会为您提供一个包含每个行序列的列表:
[[1]]
[1] "2013-01-01" "2013-01-02" "2013-01-03" "2013-01-04" "2013-01-05" "2013-01-06" "2013-01-07" "2013-01-08" "2013-01-09"
[10] "2013-01-10" "2013-01-11"
[[2]]
[1] "2013-01-22" "2013-01-23" "2013-01-24" "2013-01-25" "2013-01-26" "2013-01-27" "2013-01-28" "2013-01-29" "2013-01-30"
[[3]]
[1] "2014-02-01" "2014-02-02" "2014-02-03" "2014-02-04" "2014-02-05" "2014-02-06" "2014-02-07" "2014-02-08" "2014-02-09"
[10] "2014-02-10" "2014-02-11" "2014-02-12" "2014-02-13" "2014-02-14" "2014-02-15" "2014-02-16" "2014-02-17" "2014-02-18"
[19] "2014-02-19" "2014-02-20"
[[4]]
[1] "2014-05-12" "2014-05-13" "2014-05-14" "2014-05-15" "2014-05-16" "2014-05-17" "2014-05-18" "2014-05-19" "2014-05-20"
[10] "2014-05-21" "2014-05-22"
[[5]]
[1] "2015-02-22" "2015-02-23" "2015-02-24" "2015-02-25" "2015-02-26" "2015-02-27" "2015-02-28"
为了获得您想要的输出,我们也应该 return id 和 NoDays 列。
在 base R 中我会这样做:
getDfForDates <- function(row) {
dseq <- seq.Date( as.Date(row['StartDate']), as.Date(row['EndDate']), by='days')
data.frame( ID=row['ID'], datelist=dseq, NoDays=1)
}
rbindlist(
apply(df2,1,function(x) {
getDfForDates(x)
} )
)
另一个使用 data.table
包的解决方案是:
setDT(df2)
df2[, list(datelist=seq.Date( StartDate, EndDate, by='days'), NoDays=1), by=ID]
如果我没有遗漏一点,两者都会给出预期的结果。
我会看看我是否可以制作一个正确的 dplyr 答案,因为你似乎正在使用这个包。 在寻找 dplyr 示例时终于找到了一个骗子,投票关闭。
我们可以使用 data.table
轻松做到这一点。将'data.frame'转换为'data.table'(setDT(df2)
,如果'ID'唯一,则按'ID'分组,得到seq
=27=] 至 'EndDate' by
'ID'.
library(data.table)
res <- setDT(df2)[,list(datelist=seq(StartDate, EndDate, by='1 day'),
NoDays = 1) , by = ID]
head(res)
# ID datelist NoDays
#1: 1 2013-01-01 1
#2: 1 2013-01-02 1
#3: 1 2013-01-03 1
#4: 1 2013-01-04 1
#5: 1 2013-01-05 1
#6: 1 2013-01-06 1
如果我们需要在 dplyr
中执行此操作,我们可能需要 do
,因为 mutate
不支持此类操作
library(dplyr)
df2 %>%
rowwise() %>%
do(data.frame(ID= .$ID, datelist = seq(.$StartDate,
.$EndDate, by = '1 day'), NoDays= 1))