एक फ़ोल्डर में सभी फ़ाइलों को पढ़ें और प्रत्येक डेटा फ़्रेम में एक फ़ंक्शन लागू करें


90

मैं एक अपेक्षाकृत सरल विश्लेषण कर रहा हूं, जिसे मैंने एक विशेष फ़ोल्डर में सभी फाइलों पर एक फ़ंक्शन में रखा है। मैं सोच रहा था कि क्या किसी के पास विभिन्न फ़ोल्डरों पर प्रक्रिया को स्वचालित करने में मेरी मदद करने के लिए कोई सुझाव था।

  1. सबसे पहले, मैं सोच रहा था कि क्या एक विशेष फ़ोल्डर में सभी फ़ाइलों को सीधे आर में पढ़ने का एक तरीका था। मुझे विश्वास है कि निम्नलिखित कमांड सभी फाइलों को सूचीबद्ध करेगी:

files <- (Sys.glob("*.csv"))

... जो कि मैंने आर का उपयोग करके एक निर्दिष्ट एक्सटेंशन के साथ सभी फाइलों को सूचीबद्ध करने के लिए पाया

और फिर निम्न कोड उन सभी फाइलों को आर में पढ़ता है।

listOfFiles <- lapply(files, function(x) read.table(x, header = FALSE)) 

... आर में कई फ़ाइलों को जोड़कर

लेकिन फ़ाइलों को एक निरंतर सूची के रूप में पढ़ा जाना चाहिए और व्यक्तिगत फ़ाइलें नहीं ... मैं किसी विशेष फ़ोल्डर में सभी डेटा फ़ाइलों को व्यक्तिगत डेटाफ्रेम के रूप में खोलने के लिए स्क्रिप्ट कैसे बदल सकता हूं?

  1. दूसरे, यह मानते हुए कि मैं सभी फाइलों को अलग-अलग पढ़ सकता हूं, मैं इन सभी डेटाफ्रेमों को एक बार में कैसे पूरा कर सकता हूं। उदाहरण के लिए, मैंने चार छोटे डेटाफ़्रेम बनाए हैं ताकि मैं यह बता सकूं कि मुझे क्या चाहिए:

    Df.1 <- data.frame(A = c(5,4,7,6,8,4),B = (c(1,5,2,4,9,1)))
    Df.2 <- data.frame(A = c(1:6),B = (c(2,3,4,5,1,1)))
    Df.3 <- data.frame(A = c(4,6,8,0,1,11),B = (c(7,6,5,9,1,15)))
    Df.4 <- data.frame(A = c(4,2,6,8,1,0),B = (c(3,1,9,11,2,16)))
    

मैंने एक उदाहरण समारोह भी बनाया है:

Summary<-function(dfile){
SumA<-sum(dfile$A)
MinA<-min(dfile$A)
MeanA<-mean(dfile$A)
MedianA<-median(dfile$A)
MaxA<-max(dfile$A)

sumB<-sum(dfile$B)
MinB<-min(dfile$B)
MeanB<-mean(dfile$B)
MedianB<-median(dfile$B)
MaxB<-max(dfile$B)

Sum<-c(sumA,sumB)
Min<-c(MinA,MinB)
Mean<-c(MeanA,MeanB)
Median<-c(MedianA,MedianB)
Max<-c(MaxA,MaxB)
rm(sumA,sumB,MinA,MinB,MeanA,MeanB,MedianA,MedianB,MaxA,MaxB)

Label<-c("A","B")
dfile_summary<-data.frame(Label,Sum,Min,Mean,Median,Max)
return(dfile_summary)}

मैं प्रत्येक व्यक्तिगत डेटाफ़्रेम पर फ़ंक्शन को लागू करने के लिए आमतौर पर निम्नलिखित कमांड का उपयोग करूंगा।

Df1.summary <-Summary (dfile)

फ़ंक्शन को सभी डेटाफ़्रेम पर लागू करने के बजाय एक तरीका है, और सारांश तालिका (यानी Df1.summary) में डेटाफ़्रेम के शीर्षक का उपयोग करें।

बहुत धन्यवाद,

केटी

जवाबों:


104

इसके विपरीत, मुझे लगता है कि इसके साथ काम listकरने से ऐसी चीजों को स्वचालित करना आसान हो जाता है।

यहाँ एक समाधान है (मैंने आपके चार डेटाफ़्रेम को फ़ोल्डर में संग्रहीत किया है temp/)।

filenames <- list.files("temp", pattern="*.csv", full.names=TRUE)
ldf <- lapply(filenames, read.csv)
res <- lapply(ldf, summary)
names(res) <- substr(filenames, 6, 30)

अपनी फ़ाइलों के लिए पूर्ण पथ को संग्रहीत करना महत्वपूर्ण है (जैसा कि मैंने किया था full.names), अन्यथा आपको कार्यशील निर्देशिका को पेस्ट करना होगा, जैसे

filenames <- list.files("temp", pattern="*.csv")
paste("temp", filenames, sep="/")

काम भी करेगा। ध्यान दें कि मैंने substrपूर्ण पथ त्यागते समय फ़ाइल नाम निकालने के लिए उपयोग किया था।

आप अपनी सारांश सारणी को निम्नानुसार एक्सेस कर सकते हैं:

> res$`df4.csv`
       A              B        
 Min.   :0.00   Min.   : 1.00  
 1st Qu.:1.25   1st Qu.: 2.25  
 Median :3.00   Median : 6.00  
 Mean   :3.50   Mean   : 7.00  
 3rd Qu.:5.50   3rd Qu.:10.50  
 Max.   :8.00   Max.   :16.00  

यदि आप वास्तव में व्यक्तिगत सारांश तालिकाएँ प्राप्त करना चाहते हैं, तो आप उन्हें बाद में निकाल सकते हैं। उदाहरण के लिए,

for (i in 1:length(res))
  assign(paste(paste("df", i, sep=""), "summary", sep="."), res[[i]])

3
+1 मैं plyr::llply(या ldply) के बजाय lapplyनामों को संरक्षित करने के लिए, और अपने स्वयं के सारांश समारोह को परिभाषित करूंगा, जैसेplyr::each(min, max, mean, sd, median)
बैपटिस्ट

+1 @chl: सूची में पूर्ण नाम की चाल के लिए धन्यवाद। फ़ाइल्स फ़ंक्शन .... मैं इसे अपने उत्तर में भूल गया !!!
डिकॉआ 10

@baptiste (+1) plyrसुझाव के लिए धन्यवाद ।
chl

धन्यवाद @chl मैंने जिस फ़ंक्शन को लिखा है, मैं उपरोक्त कोड का उपयोग कैसे करूं? उदाहरण फ़ंक्शन जिसे मैंने सम, माध्य, माध्य आदि के साथ ऊपर ("सारांश") का उपयोग किया था, उदाहरण के लिए उपयोग किया गया था जिसे मैंने जल्दी बनाया था - मैं अपने वास्तविक विश्लेषण के लिए जिस वास्तविक फ़ंक्शन का उपयोग कर रहा हूं वह बहुत अधिक जटिल है। समान कोड सारांश देने के लिए उपरोक्त कोड में मैं और अधिक जटिल कार्य को कैसे शामिल करता हूं इसका कोई विचार? -
केटी

@ केटी मुझे लगता है कि आप अपने summaryकिसी भी फ़ंक्शन से बदल सकते हैं , बशर्ते कि यह एक तर्क के रूप में डेटा.फ्रेम (और / या वैकल्पिक पैरामीटर जो कि अंतर डीएफ में स्थिर हो)। उदाहरण के लिए, lapply(ldf, function(x) apply(x, 2, function(x) c(mean(x), sd(x))))माध्य और SD संगणित कोलाइड करेगा।
chl

16

आमतौर पर मैं आर में लूप के लिए उपयोग नहीं करता हूं, लेकिन यहां लूप और दो पैकेजों का उपयोग करके मेरा समाधान है: प्लायर और डॉस्टेट्स

plyr क्रेन पर है और आप https://github.com/halpo/dostats पर dostats डाउनलोड कर सकते हैं (Hadley devtools पैकेज से install_github का उपयोग कर सकते हैं )

मान लें कि मेरे पास आपके पहले दो data.frame (Df.1 और Df.2) सीएसवी फाइलों में हैं, तो आप ऐसा कुछ कर सकते हैं।

require(plyr)
require(dostats)

files <- list.files(pattern = ".csv")


for (i in seq_along(files)) {

    assign(paste("Df", i, sep = "."), read.csv(files[i]))

    assign(paste(paste("Df", i, sep = ""), "summary", sep = "."), 
           ldply(get(paste("Df", i, sep = ".")), dostats, sum, min, mean, median, max))

}

यहाँ आउटपुट है

R> Df1.summary
  .id sum min   mean median max
1   A  34   4 5.6667    5.5   8
2   B  22   1 3.6667    3.0   9
R> Df2.summary
  .id sum min   mean median max
1   A  21   1 3.5000    3.5   6
2   B  16   1 2.6667    2.5   5

(+1) ऐसा लगता है कि हमने एक ही समय में काफी जवाब दिया और आपका plyrसमाधान काफी अच्छा है!
chl

1
आपके उत्तर के लिए धन्यवाद @dickoa। मेरे द्वारा किए गए फ़ंक्शन ("सारांश") को खराब तरीके से वर्णित किया गया था। मैं इसे केवल उदाहरण के लिए उपयोग कर रहा था - मेरा वास्तविक कार्य बहुत अधिक जटिल है इसलिए मैं सोच रहा था कि उपरोक्त कोड (और शायद मेरा फ़ंक्शन) को कैसे बदला जा सकता है ताकि यह सभी अलग-अलग डेटा फ़्रेमों के लिए लागू हो (और बस नहीं आर में निर्मित कार्यों में उपयोग करें)।
केटी

2

यहाँ एक tidyverseविकल्प है जो सबसे अधिक सुरुचिपूर्ण नहीं है, लेकिन सारांश में शामिल किए जाने के संदर्भ में कुछ लचीलापन प्रदान करता है:

library(tidyverse)
dir_path <- '~/path/to/data/directory/'
file_pattern <- 'Df\\.[0-9]\\.csv' # regex pattern to match the file name format

read_dir <- function(dir_path, file_name){
  read_csv(paste0(dir_path, file_name)) %>% 
    mutate(file_name = file_name) %>%                # add the file name as a column              
    gather(variable, value, A:B) %>%                 # convert the data from wide to long
    group_by(file_name, variable) %>% 
    summarize(sum = sum(value, na.rm = TRUE),
              min = min(value, na.rm = TRUE),
              mean = mean(value, na.rm = TRUE),
              median = median(value, na.rm = TRUE),
              max = max(value, na.rm = TRUE))
  }

df_summary <- 
  list.files(dir_path, pattern = file_pattern) %>% 
  map_df(~ read_dir(dir_path, .))

df_summary
# A tibble: 8 x 7
# Groups:   file_name [?]
  file_name variable   sum   min  mean median   max
  <chr>     <chr>    <int> <dbl> <dbl>  <dbl> <dbl>
1 Df.1.csv  A           34     4  5.67    5.5     8
2 Df.1.csv  B           22     1  3.67    3       9
3 Df.2.csv  A           21     1  3.5     3.5     6
4 Df.2.csv  B           16     1  2.67    2.5     5
5 Df.3.csv  A           30     0  5       5      11
6 Df.3.csv  B           43     1  7.17    6.5    15
7 Df.4.csv  A           21     0  3.5     3       8
8 Df.4.csv  B           42     1  7       6      16

महान समाधान के रूप में यह बहुत लचीला है। मेरे डेटा प्रारूप के लिए read_csv()ठीक से काम नहीं किया इसलिए मैंने इसे बदल दिया data.table::fread()
थोरस्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.