Lesen Sie alle Dateien in einem Ordner und wenden Sie eine Funktion auf jeden Datenrahmen an


90

Ich mache eine relativ einfache Analyse, die ich in eine Funktion für alle Dateien in einem bestimmten Ordner eingefügt habe. Ich habe mich gefragt, ob jemand Tipps hat, mit denen ich den Prozess in verschiedenen Ordnern automatisieren kann.

  1. Zunächst habe ich mich gefragt, ob es eine Möglichkeit gibt, alle Dateien in einem bestimmten Ordner direkt in R zu lesen. Ich glaube, der folgende Befehl listet alle Dateien auf:

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

... die ich unter Verwenden von R gefunden habe, um alle Dateien mit einer bestimmten Erweiterung aufzulisten

Und dann liest der folgende Code alle diese Dateien in R.

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

… Vom Bearbeiten mehrerer Dateien in R.

Die Dateien scheinen jedoch als eine fortlaufende Liste und nicht als einzelne Dateien eingelesen zu werden. Wie kann ich das Skript so ändern, dass alle CSV-Dateien in einem bestimmten Ordner als einzelne Datenrahmen geöffnet werden?

  1. Zweitens: Unter der Annahme, dass ich alle Dateien separat einlesen kann, wie führe ich eine Funktion für alle diese Datenrahmen auf einmal aus. Zum Beispiel habe ich vier kleine Datenrahmen erstellt, damit ich veranschaulichen kann, was ich will:

    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)))

Ich habe mir auch eine Beispielfunktion ausgedacht:

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)}

Normalerweise würde ich den folgenden Befehl verwenden, um die Funktion auf jeden einzelnen Datenrahmen anzuwenden.

Df1.summary <-Summary (dfile)

Gibt es eine Möglichkeit, die Funktion nicht auf alle Datenrahmen anzuwenden und die Titel der Datenrahmen in den Übersichtstabellen zu verwenden (dh Df1.summary)?

Danke vielmals,

Katie

Antworten:


104

Im Gegenteil, ich denke, die Arbeit mit listmacht es einfach, solche Dinge zu automatisieren.

Hier ist eine Lösung (ich habe Ihre vier Datenrahmen in einem Ordner gespeichert 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)

Es ist wichtig, den vollständigen Pfad für Ihre Dateien zu speichern (wie ich es getan habe full.names), andernfalls müssen Sie das Arbeitsverzeichnis einfügen, z

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

wird auch funktionieren. Beachten Sie, dass ich substrDateinamen extrahiert habe, während ich den vollständigen Pfad verworfen habe.

Sie können wie folgt auf Ihre Übersichtstabellen zugreifen:

> 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  

Wenn Sie wirklich einzelne Übersichtstabellen erhalten möchten, können Sie diese anschließend extrahieren. Z.B,

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

3
+1 Ich würde plyr::llply(oder ldply) anstatt lapplydie Namen durchgehend beizubehalten und meine eigene Zusammenfassungsfunktion zu definieren, z. B.plyr::each(min, max, mean, sd, median)
baptiste

+1 @chl: danke für den Trick mit den vollständigen Namen in der Funktion list.files .... ich habe ihn in meiner Antwort vergessen !!!
Dickoa

@baptiste (+1) Danke für den plyrVorschlag.
Chl

Danke @chl. Wie verwende ich den obigen Code mit einer Funktion, die ich geschrieben habe? Die oben verwendete Beispielfunktion ("Zusammenfassung") mit Summe, Mittelwert, Median usw. wurde nur als Beispiel verwendet, das ich schnell erstellt habe - die eigentliche Funktion, die ich für meine eigentliche Analyse verwende, ist viel komplexer. Irgendwelche Ideen, wie ich eine komplexere Funktion in den obigen Code einbinden kann, um dieselben individuellen Übersichtstabellen zu erhalten? -
KT_1

@Katie Ich denke, Sie können durch summaryjede Ihrer Funktionen ersetzen , vorausgesetzt, es wird ein data.frame als Argument verwendet (und / oder optionale Parameter, die über die Differenz-DFs konstant sind). ZB lapply(ldf, function(x) apply(x, 2, function(x) c(mean(x), sd(x))))würde Mittelwert zurückgeben und SD colwise berechnen.
Chl

15

Normalerweise verwende ich keine for-Schleife in R, aber hier ist meine Lösung, die for-Schleifen und zwei Pakete verwendet: plyr und dostats

plyr ist auf cran und Sie können Dostats unter https://github.com/halpo/dostats herunterladen (möglicherweise verwenden Sie install_github aus dem Hadley devtools- Paket).

Angenommen, ich habe Ihre ersten beiden data.frame (Df.1 und Df.2) in CSV-Dateien, können Sie so etwas tun.

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))

}

Hier ist die Ausgabe

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) Es sieht so aus, als hätten wir ziemlich gleichzeitig geantwortet und Ihre plyrLösung ist ganz nett!
Chl

1
Danke @dickoa für deine Antworten. Die Funktion, die ich erfunden habe ("Zusammenfassung"), wurde schlecht beschrieben. Ich habe es nur zur Veranschaulichung verwendet - meine eigentliche Funktion ist viel komplizierter, daher habe ich mich gefragt, wie der obige Code (und wahrscheinlich meine Funktion) so geändert werden kann, dass er auf alle verschiedenen Datenrahmen angewendet wird (und nicht nur) Verwenden Sie die eingebauten Funktionen in R).
KT_1

1

Hier ist eine tidyverseOption, die vielleicht nicht die eleganteste ist, aber eine gewisse Flexibilität in Bezug auf das bietet, was in der Zusammenfassung enthalten ist:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.