簡體   English   中英

在列表上應用函數,然后在 r 中迭代第二個變量

[英]Apply function over list then iterate over second variable, in r

我正在嘗試將函數應用於列表並在 r 中迭代函數中的第二個變量。

下面是一個例子:

創建數據

A <- data.frame(var = 1:3, year = 2000:2002)
B <- data.frame(var = 4:6, year = 2000:2002)
C <- data.frame(var = 7:9, year = 2000:2002)

ABC <- list(A, B, C)

> ABC
[[1]]
  var year
1   1 2000
2   2 2001
3   3 2002

[[2]]
  var year
1   4 2000
2   5 2001
3   6 2002

[[3]]
  var year
1   7 2000
2   8 2001
3   9 2002

編寫函數: sum (它只是過濾開始年份並對“var”值求和 - 抱歉,這個簡單的函數在這個例子中比我預期的更混亂)。

library(dplyr) 

sum <- function(dat, start.year) {
  dat %>%
    filter(year >= start.year) %>%
    select(var) %>%
    colSums() %>%
    data.frame(row.names = NULL) %>%
    rename(var = '.') %>%
    mutate(start = start.year)
}

現在我可以將該函數應用於列表(和bind_rows以獲得整潔的輸出):

lapply(ABC, sum, 2000) %>%
  bind_rows()
  var start
1   6  2000
2  15  2000
3  24  2000

然而,我想要做的是迭代start.yearstart.year = c(2000, 2001, 2002)創建數據幀。 理想情況下,這將給出:

  var start
1   6  2000
2  15  2000
3  24  2000
4   5  2001
5  11  2001
6  17  2001
7   3  2002
8   6  2002
9   9  2002

我看過map2 ,但它談到使用相同長度的向量。 這在這種情況下會起作用,但想象一下我的列表中有 4 個項目,每個列表只有 3 個記錄。 所以假設map2正在做一些不同的事情。 我還考慮了nested for loop 然而,當我開始編寫它時,我意識到我將在 r 中處理 list.append 函數,這似乎是錯誤的。 我認為這是一件容易的事情。 任何幫助,將不勝感激。

我們可以使用嵌套的lapply/map來做到這一點

library(purrr)
map_dfr(2000:2002, ~ map_dfr(ABC, sum, .x))
#   var start
#1   6  2000
#2  15  2000
#3  24  2000
#4   5  2001
#5  11  2001
#6  17  2001
#7   3  2002
#8   6  2002
#9   9  2002

或者受到@thelatemail 對Map的建議的啟發

map2_dfr(rep(ABC, 3),  rep(2000:2002,each=length(ABC)), sum)

lapply

do.call(rbind, lapply(2000:2002, function(x) do.call(rbind, lapply(ABC, sum, x))))
#   var start
#1   6  2000
#2  15  2000
#3  24  2000
#4   5  2001
#5  11  2001
#6  17  2001
#7   3  2002
#8   6  2002
#9   9  2002

或者正如@thelatemail 提到的

do.call(rbind, Map(sum, ABC, start.year=rep(2000:2002,each=length(ABC))))

如果可以更改 OP 的功能,另一種選擇是

library(dplyr)
library(tidyr)
map_dfr(ABC, ~ .x %>% 
                   crossing(year2 = 2000:2002) %>% 
                   filter(year >= year2) %>%
                   group_by(year2) %>% 
                   summarise(var = base::sum(var)))

或者不是在list中執行此操作,我們可以使用bind_rows將它們綁定在一起,然后在與輸入“年” crossing后按sum進行分組

bind_rows(ABC, .id = 'grp') %>%
     group_by(grp) %>% 
     crossing(year2 = 2000:2002) %>% 
     filter(year >= year2) %>% 
     group_by(grp, year2) %>%
     summarise(var = base::sum(var))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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