簡體   English   中英

使用 for 循環將 function 應用於 R 中的列表

[英]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 領先來保持示例小。

請閱讀標簽頁面頂部的信息,特別是,示例應該是獨立的,完整的,包括所有輸入和庫語句,可重現,以便其他任何人都可以輕松運行它們並且最小化。

  1. 缺少庫語句。 R 中沒有鉛 function,因此我們假設正在使用 dplyr。
  2. 數據幀本身缺失,因此我們根據 R 中包含的 BOD 數據幀構建示例數據幀。
  3. 為了使這個最小,我們使用 2 而不是 12。

我們使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM