我在这里看到很多关于循环矢量化的问题,但是找不到任何涉及矢量化for循环以基于下面一行中的单元格的值来填充单元格(如果我是道歉的话)我只是失明了......)。
我有一个包含160万行工资的数据框,以及每个人开始赚取该工资的日期。每个人可以有多个工资,因此有多个行,每个行都有不同的更新日期。
虚拟数据集的代码如下:
df1 <- data.frame("id" = c(1,1,2,2,3,3,4,4,5,5,6,6),
"salary" = c(15456,16594,
17364,34564,
34525,33656,
23464,23467,
16794,27454,
40663,42743),
"start_date" = sample(seq(as.Date('2016/01/01'),as.Date(Sys.Date()), by="day"), 12))
df1 <- df1[order(df1$id,df1$start_date),]
我想创建一个列,其中包含每个薪水的结束日期,该列计算为后续薪资输入的前一天。如果没有后续的工资条目,则将其设置为今天的日期。这是我的代码,包括for循环,这样做:
df1$end_date <- Sys.Date()
for (i in 1:(nrow(df1)-1)){
if(df1[i,1]== df1[i+1,1]){
df1[i,4] <- df1[i+1,3]-1
}
print(i)
}
但是,我知道for
循环不是最有效的方法,但我如何进行矢量化呢?
答案 0 :(得分:2)
使用dplyr
包,您可以执行以下操作:
library(dplyr)
df1 %>%
group_by(id) %>%
mutate(end_date=lead(start_date-1,default=Sys.Date()))
返回:
id salary start_date end_date
<dbl> <dbl> <date> <date>
1 1 15456 2016-02-14 2016-03-02
2 1 16594 2016-03-03 2017-05-22
3 2 17364 2016-01-17 2016-11-28
4 2 34564 2016-11-29 2017-05-22
5 3 33656 2016-08-17 2016-11-25
6 3 34525 2016-11-26 2017-05-22
7 4 23464 2016-01-20 2017-05-05
8 4 23467 2017-05-06 2017-05-22
9 5 27454 2016-02-29 2016-12-15
10 5 16794 2016-12-16 2017-05-22
11 6 42743 2016-03-14 2017-01-29
12 6 40663 2017-01-30 2017-05-22
答案 1 :(得分:1)
您可以使用library(data.table)
:
setDT(df1)[, end_date := shift(start_date, type = "lead", fill = Sys.Date()), id][]
答案 2 :(得分:0)
使用data.table和shift,您可以使用以下内容:
df1 <- data.table("id" = c(1,1,2,2,3,3,4,4,5,5,6,6),
"salary" = c(15456,16594,
17364,34564,
34525,33656,
23464,23467,
16794,27454,
40663,42743),
"start_date" = sample(seq(as.Date('2016/01/01'),as.Date(Sys.Date()), by="day"), 12))
df1 <- df1[order(id,start_date),]
df1[, EndDate := shift(start_date, type="lead"), id]
df1[is.na(EndDate), EndDate := Sys.Date()]
答案 3 :(得分:0)
如果我理解您的问题,以下基本R代码将起作用。
df1$end <- ave(df1$start_date, df1$id, FUN=function(x) c(tail(x, -1) - 1, Sys.Date()))
ave
用于执行组级操作。执行的功能采用第二个到最终日期并减去1.这与最终日期连接。
返回
df1
id salary start_date end
1 1 15456 2016-03-20 2016-12-06
2 1 16594 2016-12-07 2017-05-22
3 2 17364 2016-10-17 2016-07-27
4 2 34564 2016-07-28 2017-05-22
5 3 34525 2016-05-26 2016-05-01
6 3 33656 2016-05-02 2017-05-22
7 4 23464 2017-04-17 2016-01-19
8 4 23467 2016-01-20 2017-05-22
9 5 16794 2016-09-12 2016-05-06
10 5 27454 2016-05-07 2017-05-22
11 6 40663 2016-10-03 2016-03-28
12 6 42743 2016-03-29 2017-05-22