[英]Create new columns by adding a sequence of months to a date column
我有日期列的數據:
library(data.table)
library(lubridate)
Y = data.table(X = c("2012-12-31", "2021-10-31"))
X
1: 2012-12-31
2: 2021-10-31
我想添加一系列月份,從 1 到x
到“X”列中的日期。 結果應該是一組新列,“X_1”、“X_2”、...“X_x”:
X X_1 X_2 X_x
1: 2012-12-31 2013-01-31 2013-02-28 .. (2012-12-31) %m+% months(x)
2: 2021-10-31 2021-11-30 2021-12-31 .. (2021-10-31) %m+% months(x)
我嘗試了幾件沒有用的事情,例如:
Y[ , c(paste0("X_", 1:15))] = AddMonths(Y$X, c(1:15)) %>% LastDayInMonth()
Y[ , c(paste0("X_", 1:15)) := AddMonths(as.IDate(X), c(1:15)) %>% LastDayInMonth()]
我想根據這個操作創建 15 列,所以我想避免for
循環。 我的真實數據有 80K 行。
%m+%
和months
都是向量化的。
library(data.table)
library(lubridate)
n = 3
nm = paste0("x", "_", seq(n))
m = rep(seq(n), each = nrow(d))
d[ , (nm) := split(x %m+% months(m), m)]
d
# x x_1 x_2 x_3
# 1: 2012-12-31 2013-01-31 2013-02-28 2013-03-31
# 2: 2021-10-31 2021-11-30 2021-12-31 2022-01-31
解釋:
設置要添加到日期列中每個值的序列中的最大月數(例如n = 3
)。 創建應將結果分配給的列名向量 ( nm = paste0("x", "_", seq(n))
)。 創建要添加 ( m = rep(seq(n), each = nrow(d))
) 到日期列的月份向量。 將 'm' 中的月份添加到 'x' 中的日期 ( x %m+% months(m)
)。 按添加到列表的月數 ( split(x %m+% months(m), m)
) 拆分結果。 使用data.table
的基本屬性,“列表的每個元素成為結果data.table
中的一列”,並通過引用 ( :=
) 分配結果列。
d = data.table(x = as.Date(c("2012-12-31","2021-10-31")))
更新:我粘貼了錯誤版本的答案: months(1)
應該是months(i-1)
。 現在更正了。
在 for 循環中,我們可以這樣做:
library(lubridate) #%m+%
Y=data.table("X"=as.Date(c("2012-12-31","2021-10-31")))
for (i in 2:15) {
Y <- Y %>%
mutate(col= X %m+% months(i-1))
colnames(Y)[i] <- paste0("X_",i-1)
}
X X_1 X_2 X_3 X_4 X_5 X_6 X_7 X_8 X_9 X_10 X_11 X_12
1: 2012-12-31 2013-01-31 2013-02-28 2013-03-31 2013-04-30 2013-05-31 2013-06-30 2013-07-31 2013-08-31 2013-09-30 2013-10-31 2013-11-30 2013-12-31
2: 2021-10-31 2021-11-30 2021-12-31 2022-01-31 2022-02-28 2022-03-31 2022-04-30 2022-05-31 2022-06-30 2022-07-31 2022-08-31 2022-09-30 2022-10-31
X_13 X_14
1: 2014-01-31 2014-02-28
2: 2022-11-30 2022-12-31
由於問題被標記為dplyr
我認為tidyverse
也是允許的。
從您擁有的 2 個日期的列表開始。
以date
作為輸入的 function 從起始月份開始添加與在附加參數中選擇的月份一樣多的月份。
然后將 function 與map
一起應用於初始日期列表。 然后將其轉換為data.frame
。
n=6
library(tidyverse)
library(lubridate)
f <- function(x, n = 5) {
yy <- x
for (i in seq(n)) {
yy <- append(yy, x %m+% months(i))
}
return(yy)
}
l <- list(("2012-12-31"), ("2021-10-31"))
l |>
map(lubridate::as_date) |>
map(n = 6, f) |>
as.data.frame() |>
setNames(l) |>
t() |> as.data.frame()
#> V1 V2 V3 V4 V5 V6
#> 2012-12-31 2012-12-31 2013-01-31 2013-02-28 2013-03-31 2013-04-30 2013-05-31
#> 2021-10-31 2021-10-31 2021-11-30 2021-12-31 2022-01-31 2022-02-28 2022-03-31
#> V7
#> 2012-12-31 2013-06-30
#> 2021-10-31 2022-04-30
請檢查此代碼
data.table("X"=c("2012-12-31","2021-10-31")) %>% mutate(date=as.Date(X), seq=row_number(), date2=date %m+% months(15)) %>%
group_by(seq) %>%
pivot_longer(starts_with('date'), names_to = 'name', values_to = 'date') %>%
tidyr::complete(date=full_seq(date, period = 1)) %>% fill(X) %>%
mutate(year=year(date), month=month(date)) %>% group_by(X,year, month) %>%
slice_tail(n=1) %>% ungroup %>% group_by(X) %>%
mutate(row=row_number()) %>%
pivot_wider(X,names_from = row, names_prefix = 'X',values_from = date)
創建於 2023-01-28,使用reprex v2.0.2
# A tibble: 2 × 17
# Groups: X [2]
X X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
<chr> <date> <date> <date> <date> <date> <date> <date> <date> <date> <date> <date>
1 2012-12-31 2012-12-31 2013-01-31 2013-02-28 2013-03-31 2013-04-30 2013-05-31 2013-06-30 2013-07-31 2013-08-31 2013-09-30 2013-10-31
2 2021-10-31 2021-10-31 2021-11-30 2021-12-31 2022-01-31 2022-02-28 2022-03-31 2022-04-30 2022-05-31 2022-06-30 2022-07-31 2022-08-31
# … with 5 more variables: X12 <date>, X13 <date>, X14 <date>, X15 <date>, X16 <date>
# ℹ Use `colnames()` to see all variable names
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.