[英]Using a for loop to apply a function to a list in R
我有四個數據框,每個都有兩列,一列用於日期,另一列用於值。 我想在每個數據框中生成 24 個新列,12 個用於滯后指標,12 個用於領先指標。 我已經設法使用以下代碼一次完成一個數據幀:
df[paste0("lag", 1:12)] = lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] = lapply(1:12, lead, x=df[,2])
但是,我想使用遍歷數據幀列表的 for 循環來自動執行此操作。 到目前為止,我已經嘗試了以下方法:
dataframes = list(df1,df2,df3,df4)
for (df in dataframes){
df[paste0("lag", 1:12)] = lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] = lapply(1:12, lead, x=df[,2])
}
可悲的是,這不起作用,因為數據幀在 for 循環之后保持不變。 關於如何完成這項工作的任何建議?
df
不會更新全局環境中的原始 object 'df1', 'df2'。 如果我們願意,可以使用assign
(或者更好的方法是將它保存在list
)
# // create a named `list`
dataframes = list(df1,df2,df3,df4)
names(dataframes) <- c("df1", "df2", "df3", "df4")
# // loop over the names of the list
for(nm in names(dataframes)) {
# // get the value of the object from the names
df <- get(nm)
# // create the new columns
df[paste0("lag", 1:12)] <- lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] <- lapply(1:12, lead, x=df[,2])
# // assign to update the original object
assign(nm, df)
}
將其保存在list
中可能會更好
dataframes2 <- lapply(dataframes, function(df) {
df[paste0("lag", 1:12)] <- lapply(1:12, lag, x=df[,2])
df[paste0("lead", 1:12)] <- lapply(1:12, lead, x=df[,2])
df
})
list
output 可用於使用list2env
更新原始對象,但不推薦
list2env(dataframe2, .GlobalEnv)
讓 nms 是數據幀名稱的向量,並從中創建數據幀本身的列表 L。 我們使用 2 滯后和 2 領先來保持示例小。
請閱讀r標簽頁面頂部的信息,特別是,示例應該是獨立的,完整的,包括所有輸入和庫語句,可重現,以便其他任何人都可以輕松運行它們並且最小化。
我們使用 mget 創建數據幀的命名列表 L,然后遍歷名稱,在 L 中創建新數據幀,覆蓋 L 中的舊數據幀。盡管不推薦,除非有充分的理由這樣做,我們可以在 L 中寫入數據幀使用listenv(L, .GlobalEnv)
回到全局環境。
library(dplyr)
# test data
for(i in 1:4) assign(paste0("df", i), i * BOD)
nms <- paste0("df", 1:4)
L <- mget(nms)
for (nm in names(L)) {
L[[nm]][paste0("lag", 1:2)] = lapply(1:2, lag, x=L[[nm]][,2])
L[[nm]][paste0("lead", 1:2)] = lapply(1:2, lead, x=L[[nm]][,2])
}
給予:
> str(L)
List of 4
$ df1:'data.frame': 6 obs. of 6 variables:
..$ Time : num [1:6] 1 2 3 4 5 7
..$ demand: num [1:6] 8.3 10.3 19 16 15.6 19.8
..$ lag1 : num [1:6] NA 8.3 10.3 19 16 15.6
..$ lag2 : num [1:6] NA NA 8.3 10.3 19 16
..$ lead1 : num [1:6] 10.3 19 16 15.6 19.8 NA
..$ lead2 : num [1:6] 19 16 15.6 19.8 NA NA
$ df2:'data.frame': 6 obs. of 6 variables:
..$ Time : num [1:6] 2 4 6 8 10 14
..$ demand: num [1:6] 16.6 20.6 38 32 31.2 39.6
..$ lag1 : num [1:6] NA 16.6 20.6 38 32 31.2
..$ lag2 : num [1:6] NA NA 16.6 20.6 38 32
..$ lead1 : num [1:6] 20.6 38 32 31.2 39.6 NA
..$ lead2 : num [1:6] 38 32 31.2 39.6 NA NA
$ df3:'data.frame': 6 obs. of 6 variables:
..$ Time : num [1:6] 3 6 9 12 15 21
..$ demand: num [1:6] 24.9 30.9 57 48 46.8 59.4
..$ lag1 : num [1:6] NA 24.9 30.9 57 48 46.8
..$ lag2 : num [1:6] NA NA 24.9 30.9 57 48
..$ lead1 : num [1:6] 30.9 57 48 46.8 59.4 NA
..$ lead2 : num [1:6] 57 48 46.8 59.4 NA NA
$ df4:'data.frame': 6 obs. of 6 variables:
..$ Time : num [1:6] 4 8 12 16 20 28
..$ demand: num [1:6] 33.2 41.2 76 64 62.4 79.2
..$ lag1 : num [1:6] NA 33.2 41.2 76 64 62.4
..$ lag2 : num [1:6] NA NA 33.2 41.2 76 64
..$ lead1 : num [1:6] 41.2 76 64 62.4 79.2 NA
..$ lead2 : num [1:6] 76 64 62.4 79.2 NA NA
編寫更明確的 function(如果需要),會給您更多的靈活性。 使用您的示例,但簡化表格
a <- tibble(x = 1:50)
b <- tibble(x = 51:75)
dflist <- list(a, b)
# quick function using single lag on single column, but easily extendible
cv <- function(a)
{
nca <- ncol(a)
for(i in seq(from = 1, to = 23, by = 2))
{
a[nca+i] = lag(a$x)
a[nca+i+1] = lead(a$x)
}
return(a)
}
# simple to apply to create your new columns (or put in loop)
na <- cv(a)
# or simple to do all df at once and concatenate the results
f <- dflist %>% map_dfr(cv)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.