2017-04-27 107 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")