2017-04-27 72 views
1

我有一个包含500多个.dta文件的文件夹。我想将这些文件加载​​到一个R对象中。加载多个.dta文件

我的.dta文件的通用名称由四部分组成:'两个字母/四位数字/ y/.dta'。例如,名称可以是'de2015y.dta'或'fr2008y.dta'。只有对应于两个字母和四位数的部分在.dta文件中发生变化。

我写了一个代码,但我不满意它。我想避免使用循环并缩短它。

我的代码是:

# Select the .dta files I want to load 
#..................................... 

name <- list.files(path="E:/Folder") # names of the .dta files in the folder 
db <- as.data.frame(name) 
db$year <- substr(db$name, 3, 6) 
db <- subset (db, year == max(db$year)) # keep last year available 
db$country <- substr(db$name, 1, 2) 
list.name <- as.list(db$country) 


# Loading all the .dta files in the Global environment 
#.................................................. 

for(i in c(list.name)){ 
    obj_name <- paste(i, '2015y', sep='') 
    file_name <- file.path('E:/Folder',paste(obj_name,'dta', sep ='.')) 
    input <- read.dta13(file_name) 
    assign(obj_name, value = input) 
} 


# Merge the files into a single object 
#.................................................. 

df2015 <- rbind (at2015y, be2015y, bg2015y, ch2015y, cy2015y, cz2015y, dk2015y, ee2015y, ee2015y, es2015y, fi2015y, 
       fr2015y, gr2015y, hr2015y, hu2015y, ie2015y, is2015y, it2015y, lt2015y, lu2015y, lv2015y, mt2015y, 
       nl2015y, no2015y, pl2015y, pl2015y, pt2015y, ro2015y, se2015y, si2015y, sk2015y, uk2015y) 

有谁知道我怎么能避免使用一个循环,并缩短我的代码?

回答

0

我会更改此任务的工作目录... 然后,这是否做你所要求的?

setwd("C:/.../yourfiles") 

# get file names where year equals "2015" 
name=list.files(pattern="*.dta") 
name=name[substr(name,3,6)=="2015"] 

# read in the files in a list 
files=lapply(name,foreign::read.dta) 

# remove ".dta" from file names and 
# give the file contents in the list their name 
names(files)=lapply(name,function(x) substr(x, 1, nchar(x)-4)) 
#or alternatively 
names(files)=as.list(substr(name,1,nchar(name)-4)) 

# optional: put all file contents into one data-frame 
#(data-frames (vectors) need to have the same row counts (lengths) for this last step to work) 
mydatafrm = data.frame(files) 
+0

谢谢@Alias为你编码。它工作得很好。但是,您是否知道我如何在数据框中转换“文件”? –

+0

@DavidMarguerit,如果你读入的文件包含向量或数据帧,那么你可以这样做:'mydataframe = data.frame(files)'。这个统一的数据框的列名将与原始列名相同,但是您将能够确定哪个列来自哪个文件,因为列名不仅包含原始列名,还包含名称它们来自的矢量/数据帧。因此,在统一数据框中,列名将具有以下结构:_origin-name.column-name_。这种自动命名需要命名列表组件。 – Alias

0

以下步骤应该给你你想要的东西:

  1. 装入foreign包:

    library(foreign) # or alternatively: library(haven) 
    
  2. 创建的文件名列表

    file.list <- list.files(path="E:/Folder", pattern='*.dat', full.names = TRUE) 
    
  3. 确定哪些文件读取(注意:您要检查,如果这些都是正确的位置substr它是从我的身边的估计)

    vec <- as.integer(substr(file.list,13,16)) 
    file.list2 <- file.list[vec==max(vec)] 
    
  4. 读取文件

    df.list <- sapply(file.list2, read.dta, simplify=FALSE) 
    
  5. 删除从listnames

    names(df.list) <- gsub("E:/Folder","",names(df.list)) 
    
  6. 绑定的所述dataframes在一起一个data.frame/data.table并创建一个ID-路径列以及

    library(data.table) 
    df <- rbindlist(df.list, idcol = "id") 
    
    # or with 'dplyr' 
    library(dplyr) 
    df <- bind_rows(df.list, .id = "id") 
    

现在你有一个ID列标识不同的原始文件data.frame。

1

您还可以使用purrr来完成您的任务。

首先创建一个你想加载的所有文件的命名向量(因为我理解你的问题,你只需要从2015年开始的所有文件)。 setNames()部分仅用于在数据框中需要ID变量并且尚未包含在.dta文件中的情况。

之后,只需使用map_df()来读取所有文件并返回一个数据帧。指定.id是可选的,并生成一个ID列,其值基于in_files的名称。

library(purrr) 
library(haven) 

in_files <- list.files(path="E:/Folder", pattern = "2015y", full.names = TRUE) 
in_files <- setNames(in_files, in_files) 

df2015 <- map_df(in_files, read_dta, .id = "id")