如何使用循环通过子集化和合并 R 中的许多不同数据帧来创建面板数据?

How to use a loop to create panel data by subsetting and merging a lot of different data frames in R?

我环顾四周,但找不到答案!

我已经将大量数据集导入到 R。

每个数据集包含一年的信息(例如 df_2012、df_2013、df_2014 等)。

所有数据集都具有相同的 variables/columns(例如 df_2012 中的 varA_2012 对应 df_2013 中的 varA_2013。

我想用我的 id 变量和 varA_2012、varB_2012、varA_2013、varB_2013、varA_2014、[=42= 创建一个 df ]等

我正在尝试创建一个循环,帮助我在每个数据框中提取我感兴趣的几列(varA_XXXX、varB_XXXX),然后进行基于完整连接的操作在我的 id var.

我已经很久没有使用 R 了...

到目前为止,我试过这个:

id <- c("France", "Belgium", "Spain")

varA_2012 <- c(1,2,3)
varB_2012 <- c(7,2,9)
varC_2012 <- c(1,56,0)
varD_2012 <- c(13,55,8)

varA_2013 <- c(34,3,56)
varB_2013 <- c(2,53,5)
varC_2013 <- c(24,3,45)
varD_2013 <- c(27,13,8)

varA_2014 <- c(9,10,5)
varB_2014 <- c(95,30,75)
varC_2014 <- c(99,0,51)
varD_2014 <- c(9,40,1)


df_2012 <-data.frame(id, varA_2012, varB_2012, varC_2012, varD_2012)

df_2013 <-data.frame(id, varA_2013, varB_2013, varC_2013, varD_2013)

df_2014 <-data.frame(id, varA_2014, varB_2014, varC_2014, varD_2014)

year = c(2012:2014)

for(i in 1:length(year)) { 

df_[i] <- df_[I][df_[i]$id, df_[i]$varA_[i], df_[i]$varB_[i], ]

  list2env(df_[i], .GlobalEnv)
}

panel_df <- Reduce(function(x, y) merge(x, y, by="if"), list(df_2012, df_2013, df_2014))

我知道这里可能有很多错误。

这里有几个选项;但是,不清楚您希望预期的输出是什么样子。

如果你想要宽幅面,那么我们可以用tidyverse来做:

library(tidyverse)

results <-
  map(list(df_2012, df_2013, df_2014), function(x)
    x %>% dplyr::select(id, starts_with("varA"), starts_with("varB"))) %>%
  reduce(., function(x, y)
    left_join(x, y, all = TRUE, by = "id"))

输出

       id varA_2012 varB_2012 varA_2013 varB_2013 varA_2014 varB_2014
1 Belgium         2         2         3        53        10        30
2  France         1         7        34         2         9        95
3   Spain         3         9        56         5         5        75

但是,如果您需要长格式,那么我们可以旋转数据:

results %>%
  pivot_longer(-id, names_to = c("variable", "year"), names_sep = "_")

输出

   id      variable year  value
   <chr>   <chr>    <chr> <dbl>
 1 France  varA     2012      1
 2 France  varB     2012      7
 3 France  varA     2013     34
 4 France  varB     2013      2
 5 France  varA     2014      9
 6 France  varB     2014     95
 7 Belgium varA     2012      2
 8 Belgium varB     2012      2
 9 Belgium varA     2013      3
10 Belgium varB     2013     53
11 Belgium varA     2014     10
12 Belgium varB     2014     30
13 Spain   varA     2012      3
14 Spain   varB     2012      9
15 Spain   varA     2013     56
16 Spain   varB     2013      5
17 Spain   varA     2014      5
18 Spain   varB     2014     75

或者如果对宽格式使用 base R,那么我们可以这样做:

results <-
  lapply(list(df_2012, df_2013, df_2014), function(x)
    subset(x, select = c("id", names(x)[startsWith(names(x), "varA")], names(x)[startsWith(names(x), "varB")])))

results <-
  Reduce(function(x, y)
    merge(x, y, all = TRUE, by = "id"), results)

根据您最初的 for 循环尝试,下面的代码似乎可能有所帮助

> (df <- Reduce(merge, list(df_2012, df_2013, df_2014)))[grepl("^(id|var(A|B))",names(df))]
       id varA_2012 varB_2012 varA_2013 varB_2013 varA_2014 varB_2014
1 Belgium         2         2         3        53        10        30
2  France         1         7        34         2         9        95
3   Spain         3         9        56         5         5        75