R 中 loop/repeat 的问题

Problems with loop/repeat in R

为了最终得到 45 个不同的矩阵,我需要多次执行此代码:mat[j], j=1:45。 不确定如何使用 "for-loop" 来实现这一点,如有任何提示,我们将不胜感激。 数据文件存储在这里,逐年 https://intl-atlas-downloads.s3.amazonaws.com/index.html

library(readstata13)  
library(diverse)   
library(plyr)   

for (j in 1:45) {
  dat <- read.dta13(file.choose())

  data = aggregate(dat$export_value, by = list(dat$exporter,dat$commoditycode), FUN = sum)

  colnames(data) = c("land","product","value")  

  dt = split(data, f = data$product)  

  land = as.data.frame(sort(unique(data[, 1])))  

  nds = seq(1, nrow(land), by = 1)  

  texmat = cbind(nds, land)  

  colnames(texmat) = c("num", "land")  

  for (i in 1:length(unique(data[, 2]))) {
    (join(texmat, dt[[i]], by = "land", type = "left")$value)
  }   

  mt = sapply(1:length(unique(data[, 2])), function(i) join(texmat, dt[[i]], by = "land", type = "left")$value)   

  colnames(mt) = unique(data[, 2])   

  rownames(mt) = sort(unique(data[, 1]))   

  mt[is.na(mt)] = 0   

  rcamat=values(mt, category_row = FALSE, norm = "rca",filter = 1, binary = TRUE)   

  rcamat[is.na(rcamat)] = 0   

  tmat = rcamat[rowSums(rcamat) != 0, , drop = TRUE]   

  mat = t(tmat)
}  

看来您几乎已经掌握了 for 循环。你只需要添加2个概念:

1) 创建要在开始时读取的矩阵列表。像这样的结构:

filenames <- paste0('H0_',1995:2016,'.dta')
filenames <- c(filenames,paste0('S2_final_',1962:2016,'.dta'))

创建一个你想要读取的文件的向量将允许你将 file.choose 替换为类似以下内容(在循环内):

dat <- read.dta13(paste0('/path/to/directory/with/files/',filenames[i]))

这样您就可以在每次循环迭代时抓取一个新文件。

2) 在循环结束时存储输出矩阵。您可以通过将它们全部放在列表中或使用 assign 创建对象集合来实现。我更喜欢列表方法:

#before the for loop initialize a NULL list:
mats <- NULL
#at the end of the loop, (after mat = t(tmat) but before the close bracket) add this line to add it to the list
mats[[i]] <- mat

这将创建一个列表 mats,其中 mats[[1]] 包含第一个矩阵,mats[[2]] 包含第二个矩阵,依此类推。

您也可以像这样创建一堆对象:

#at the end of the for loop add
assign(paste0('mat_',i),mat)

这将创建 mat_1mat_2 等作为单独的对象。完整的实现看起来像这样:

library(readstata13)  
library(diverse)   
library(plyr)   
setwd('/path/to/files/')

filenames <- paste0('H0_',1995:2016,'.dta')
filenames <- c(filenames,paste0('S2_final_',1962:2016,'.dta'))
#you'll have to prune this to the files you actually want, as this list is more than 45

finished_matrices <- NULL
for (j in 1:45) {
  dat <- read.dta13(filenames[i]) #pickup    
  data = aggregate(dat$export_value, by = list(dat$exporter,dat$commoditycode), FUN = sum)
  colnames(data) = c("land","product","value")      
  dt = split(data, f = data$product)      
  land = as.data.frame(sort(unique(data[, 1])))      
  nds = seq(1, nrow(land), by = 1)      
  texmat = cbind(nds, land)     
  colnames(texmat) = c("num", "land")  

  for (i in 1:length(unique(data[, 2]))) {
    (join(texmat, dt[[i]], by = "land", type = "left")$value)
  }   

  mt = sapply(1:length(unique(data[, 2])), function(i) join(texmat, dt[[i]], by = "land", type = "left")$value)    
  colnames(mt) = unique(data[, 2])       
  rownames(mt) = sort(unique(data[, 1]))      
  mt[is.na(mt)] = 0      
  rcamat=values(mt, category_row = FALSE, norm = "rca",filter = 1, binary = TRUE)     
  rcamat[is.na(rcamat)] = 0     
  tmat = rcamat[rowSums(rcamat) != 0, , drop = TRUE]    
  mat = t(tmat)
  finished_matrices[[i]] <- mat
}