R 跨行向量化迭代操作

R 跨行向量化迭代操作,r,for-loop,data.table,vectorization,R,For Loop,Data.table,Vectorization,我在这里看到了很多关于循环矢量化的问题,但是找不到任何涉及到基于下面一行单元格的值矢量化for循环以填充单元格的问题(如果我只是瞎了眼睛,请道歉…) 我有一个包含160万行工资和每个人开始赚取工资的日期的数据框。每个人都可以有多个工资,因此可以有多个行,每个行都有不同的更新日期 虚拟数据集的代码如下所示: df1 <- data.frame("id" = c(1,1,2,2,3,3,4,4,5,5,6,6), "salary" = c(15456,165

我在这里看到了很多关于循环矢量化的问题,但是找不到任何涉及到基于下面一行单元格的值矢量化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),]
df1您可以使用
库(data.table)

您可以使用
库(data.table)


使用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()]

df1对于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()]

df1如果我理解你的问题,下面的基本R代码就可以了

df1$end <- ave(df1$start_date, df1$id, FUN=function(x) c(tail(x, -1) - 1, Sys.Date()))

如果我理解你的问题,下面的基本R代码将起作用

df1$end <- ave(df1$start_date, df1$id, FUN=function(x) c(tail(x, -1) - 1, Sys.Date()))

使用
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
id工资开始日期结束日期
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

使用
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
id工资开始日期结束日期
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

这适用于每个id的第一行,但将每个id的最后一行设置为第一行日期的前一天,而我在今天的日期之后。这适用于每个id的第一行,但将每个id的最后一行设置为第一行日期的前一天,而我在今天的日期之后。请参阅我答案的注释,他希望
Sys.Date()
用于
end\u Date
如果
start\u Date
是每个id的最新日期,…我也在相同的陷阱中运行。啊哈。感谢您的澄清。请参阅我回答中的评论,他希望
Sys.Date()
用于
end\u Date
如果
start\u Date
是每个id的最新日期,…我也会陷入同样的陷阱。啊哈。谢谢你的澄清。