【问题标题】:How can I refer to multiple databases using the same looping vector in R?如何在 R 中使用相同的循环向量引用多个数据库?
【发布时间】:2026-02-04 08:30:01
【问题描述】:

我需要通过合并、聚合和拆分数据帧来执行各种操作。这些行动需要连续几年重复(2000 年、2001 年、2002 年等)。但是,我找不到一种方法来引用基于带有年份的循环字符串的多个数据帧。

一个例子: 我想合并同一年的 3 个数据框。我当前的代码:

Stake_2000 <- combine(A2000, B2000, C2000)
Stake_2001 <- combine(A2001, B2001, C2001)
Stake_2002 <- combine(A2002, B2002, C2002)
Stake_2003 <- combine(A2003, B2003, C2003)
Stake_2004 <- combine(A2004, B2004, C2004)
Stake_2005 <- combine(A2005, B2005, C2005)

我想通过循环中的变量替换年份来简化。但是,我无法让 R 从适当的数据帧中读取。我曾多次尝试搁浅:

names <- c("2000", "2001", "2002", "2003", "2004", "2005")
for (n in names)
{Temp <- combine(c("A",n,sep=""), (c"B",n,sep=""), c("C",n,sep=""))
assign(paste("Stake_",n,sep=""), Temp)}

or replace combine function with combine(An, Bn, Cn), or combine(A+n, B+n, C+n)

除了这些操作之外,我还需要从不同的数据库中聚合和匹配这些年来遇到的类似问题。例如,将所有“2000”替换为循环中的后续年份:

Temp <- aggregate(VarA~VarB, data=A_2000, FUN=length)
S_2000$VarC <- Temp[match(S_2000$ID, Temp$ID), "VarA"]

我想有一些非常直接的答案,但我一直没能找到。

【问题讨论】:

  • 我猜你错过了paste,即paste(c('A', n, sep='')。最好提供一个可重现的小例子*.com/questions/5963269/…
  • 谢谢。我会做一个可重现的例子。不幸的是,插入粘贴也不起作用。

标签: r loops dataframe


【解决方案1】:

你可以试试

library(dplyr)
names <- c("2000", "2001", "2002", "2003", "2004", "2005")
for(n in names){
   Temp <- bind_cols( get(paste0('A', n)), get(paste0('B', n)),
                get(paste0('C', n)))
      assign(paste0('Stake_', n), Temp)
 }

identical(cbind(A2000, B2000, C2000), Stake_2000)
#[1] TRUE

 identical(cbind(A2005, B2005, C2005), Stake_2005)
#[1] TRUE

对于aggregate,你可以这样做

 lapply(mget(paste0('A', 2000:2005)), function(x)
                       aggregate(V1~V2, x, FUN=length))

BC 也是如此,尽管尚不清楚 S_2000 是什么。

更新

如果行数不同,我们可以使用combinestri_list2matrix from stringi

A2000 <- rbind(A2000, c(4,8, 9 , 15, 25))
library(stringi)
for(n in names){
  Temp <- as.data.frame(stri_list2matrix(combine( get(paste0('A', n)), 
    get(paste0('B', n)), get(paste0('C', n)))), stringsAsFactors=FALSE)
  Temp[] <- lapply(Temp, as.numeric)
  assign(paste0('Stake_', n), Temp)
 }
Stake_2000
#   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15
#1  6 19 12 18  1  1 18  5  7  17   9  19  12  18   8
#2  4  5  7  4 11 12  9  1  2   5   4  13  18   5   6
#3 14 16 14  0 15  3  7 13 20   0   4   3   0   0   6
#4 10 16 14 10  2  4 10  6 13  16   4   2   6   8  15
#5 13  5  6  2  4 12 11  0 10  16   9  17  12   7   6
#6  4  8  9 15 25 NA NA NA NA  NA  NA  NA  NA  NA  NA

数据

set.seed(24)
list2env(setNames(lapply(1:6, function(i) 
  as.data.frame(matrix(sample(0:20, 5*5, replace=TRUE), ncol=5))),
     paste0('A', 2000:2005)), envir=.GlobalEnv)
list2env(setNames(lapply(1:6, function(i) 
   as.data.frame(matrix(sample(0:20, 5*5, replace=TRUE), ncol=5))),
       paste0('B', 2000:2005)), envir=.GlobalEnv)
 list2env(setNames(lapply(1:6, function(i) 
   as.data.frame(matrix(sample(0:20, 5*5, replace=TRUE), ncol=5))), 
      paste0('C', 2000:2005)), envir=.GlobalEnv)    

【讨论】:

  • 该示例完美运行。我认为症结在于 get(paste0(.. 命令。但是,使用原始数据时,使用函数 combine.bind_cols 会得到一个大列表而不是数据框。bind_cols 会出错,因为数据框的数量不同行。现在正在处理聚合示例,看看我是否可以让它工作。(必须在受到严格保护的远程桌面和其他计算机之间切换,所以需要一段时间)
  • @MattheeleCointre 首先我使用了combine,但结果是一个列表,我们可以将其转换回data.frame。如果列表元素的长度不同,我们可以使用library(stringi); stri_list2matrix(Stake_2000)
  • @MattheeleCointre 更新了帖子,请检查是否有帮助
  • 非常感谢!我现在让他们俩都在工作。也会尝试使用这些知识来循环我的其他操作。
最近更新 更多