Bir klasördeki tüm dosyaları okuyun ve her veri çerçevesine bir işlev uygulayın


90

Belirli bir klasördeki tüm dosyalar üzerinde, bir işleve yerleştirdiğim nispeten basit bir analiz parçası yapıyorum. İşlemi birkaç farklı klasörde otomatikleştirmeme yardımcı olacak herhangi bir ipucu olup olmadığını merak ediyordum.

  1. Öncelikle, belirli bir klasördeki tüm dosyaları doğrudan R'ye okumanın bir yolu olup olmadığını merak ediyordum. Aşağıdaki komutun tüm dosyaları listeleyeceğine inanıyorum:

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

... belirli bir uzantıya sahip tüm dosyaları listelemek için R Kullanarak bulduğum

Ve sonra aşağıdaki kod tüm bu dosyaları R'ye okur.

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

R'de birden çok dosyayı manipüle etmekten

Ancak dosyalar tek tek dosyalar değil, sürekli bir liste olarak okunuyor gibi görünüyor… Belirli bir klasördeki tüm csv dosyalarını ayrı veri çerçeveleri olarak açmak için komut dosyasını nasıl değiştirebilirim?

  1. İkinci olarak, tüm dosyaları ayrı ayrı okuyabileceğimi varsayarsak, tüm bu veri çerçeveleri üzerinde bir işlevi tek seferde nasıl tamamlarım. Örneğin, ne istediğimi gösterebilmek için dört küçük veri çerçevesi oluşturdum:

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

Ayrıca bir örnek işlev oluşturdum:

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

İşlevi her bir veri çerçevesine uygulamak için normalde aşağıdaki komutu kullanırdım.

Df1.summary <-Summary (dfile)

Fonksiyonu tüm veri çerçevelerine uygulamak ve veri çerçevelerinin başlıklarını özet tablolarda kullanmak yerine (örn. Df1.summary) bir yol var mı?

Çok teşekkürler,

Katie

Yanıtlar:


104

Aksine, birlikte çalışmanın listbu tür şeyleri otomatikleştirmeyi kolaylaştırdığını düşünüyorum .

İşte bir çözüm (dört veri çerçevenizi klasörde sakladım 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)

Dosyalarınızın tam yolunu saklamak önemlidir (benim yaptığım gibi full.names), aksi takdirde çalışma dizinini yapıştırmanız gerekir, örn.

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

çok çalışacak. Ben kullanılan Not substrtam yol atmadan ederken özü dosya adlarına.

Özet tablolarınıza aşağıdaki şekilde erişebilirsiniz:

> 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  

Gerçekten bireysel özet tabloları almak istiyorsanız, bunları daha sonra çıkarabilirsiniz. Örneğin,

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

3
1 yapardım plyr::llply(veya ldplybunun yerine) lapplygenelinde adları korumak ve örneğin kendi özet işlevini tanımlamakplyr::each(min, max, mean, sd, median)
baptiste

+1 @chl: list.files işlevindeki tam adlar için teşekkürler .... Cevabımda unuttum !!!
dickoa

@baptiste (+1) plyrÖneriniz için teşekkürler .
chl

Teşekkürler @chl. Yukarıdaki kodu yazdığım bir fonksiyonla nasıl kullanırım? Yukarıda toplam, ortalama, medyan vb. İle kullandığım örnek fonksiyon ("Özet") sadece hızlı bir şekilde oluşturduğum bir örnek olarak kullanıldı - gerçek analizim için kullandığım gerçek fonksiyon çok daha karmaşık. Aynı özet tablolarını vermek için yukarıdaki koda daha karmaşık bir işlevi nasıl dahil ettiğime dair herhangi bir fikriniz var mı? -
KT_1

@Katie Argüman olarak bir data.frame summary(ve / veya DF'ler arasında sabit olan isteğe bağlı parametreler) alması koşuluyla, sizin herhangi bir fonksiyonunuzla değiştirebilirsiniz . Örneğin, lapply(ldf, function(x) apply(x, 2, function(x) c(mean(x), sd(x))))ortalama döndürür ve SD sütun şeklinde hesaplanır.
chl

16

genellikle R'de döngü için kullanmıyorum, ancak burada döngüler ve iki paket için kullandığım çözüm: plyr ve dostats

plyr karter üzerinde olduğunu ve indirebilirsiniz dostats üzerinde https://github.com/halpo/dostats (Hadley gelen install_github kullanıyor olabilir DevTools'un paketi)

İlk iki data.frame'inizin (Df.1 ve Df.2) csv dosyalarında olduğunu varsayarak, bunun gibi bir şey yapabilirsiniz.

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

}

İşte çıktı

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) Aynı anda cevap vermişiz gibi görünüyor ve plyrçözümünüz oldukça güzel!
chl

1
Cevaplarınız için teşekkürler @dickoa. Oluşturduğum işlev ("Özet") yeterince tanımlanmamıştı. Bunu sadece açıklama amacıyla kullanıyordum - benim gerçek işlevim çok daha karmaşıktır, bu nedenle yukarıdaki kodun (ve muhtemelen işlevimin) tüm farklı veri çerçevelerine uygulanacak şekilde nasıl değiştirilebileceğini merak ediyordum (ve sadece R) 'deki yerleşik işlevleri kullanın.
KT_1

2

İşte tidyverseen şık olmayabilecek, ancak özete dahil edilenler açısından biraz esneklik sunan bir seçenek:

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

Çok esnek olduğu için harika bir çözüm. Veri formatım read_csv()düzgün çalışmadığı için onu ile değiştirdim data.table::fread().
Thorsten
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.