フォルダ内のすべてのファイルを読み取り、各データフレームに関数を適用します


90

特定のフォルダー内のすべてのファイルに対して、関数に入れた比較的単純な分析を行っています。さまざまなフォルダでプロセスを自動化するのに役立つヒントが誰かあるかどうか疑問に思いました。

  1. まず、特定のフォルダー内のすべてのファイルをRに直接読み取る方法があるかどうか疑問に思いました。次のコマンドですべてのファイルが一覧表示されると思います。

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

... Rを使用して指定された拡張子を持つすべてのファイルを一覧表示することで見つけました

そして、次のコードはそれらすべてのファイルをRに読み込みます。

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

Rで複数のファイル操作することから

しかし、ファイルは個々のファイルではなく、1つの連続したリストとして読み込まれるようです。スクリプトを変更して、特定のフォルダー内のすべてのcsvファイルを個々のデータフレームとして開くにはどうすればよいですか。

  1. 次に、すべてのファイルを個別に読み取ることができると仮定して、これらすべてのデータフレームで関数を一度に完了するにはどうすればよいですか。たとえば、4つの小さなデータフレームを作成したので、必要なものを説明できます。

    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することで、そのようなことを簡単に自動化できると思います。

これが1つの解決策です(4つのデータフレームをフォルダーに保存しました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:list.files関数のフルネームトリックに感謝します....私は私の答えでそれを忘れました!!!
dickoa 2012年

@baptiste(+1)plyr提案をありがとう。
chl 2012年

@chlに感謝します。私が書いた関数で上記のコードを使用するにはどうすればよいですか?上記で使用した合計、平均、中央値などの関数の例(「要約」)は、すばやく作成した例として使用されました。実際の分析に使用している実際の関数は、はるかに複雑です。より複雑な関数を上記のコードに組み込んで、同じ個別の要約テーブルを作成する方法についてのアイデアはありますか?–
KT_1 2012年

@Katiesummary引数としてdata.frame(および/または差分DF全体で一定のオプションのパラメーター)を使用する場合は、任意の関数に置き換えることができると思います。たとえば、lapply(ldf, function(x) apply(x, 2, function(x) c(mean(x), sd(x))))colwiseで計算された平均とSDを返します。
chl 2012年

16

通常、Rではforループを使用しませんが、forループと2つのパッケージ(plyrdostats)を使用したソリューションを次に示します。

plyrクラン上にあり、https://github.com/halpo/dostatsからdostatsをダウンロードできます(Hadley devtoolsパッケージのinstall_githubを使用している可能性があります)

csvファイルに最初の2つの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 2012年

1
回答ありがとうございます@dickoa。私が作った機能(「要約」)はあまり説明されていませんでした。私はそれを説明の目的で使用していました-私の実際の関数ははるかに複雑なので、上記のコード(そしておそらく私の関数)をどのように変更して、すべての異なるデータフレームに適用できるのか疑問に思いました(そしてそれだけではありません) Rの組み込み関数を使用します)。
KT_1 2012年

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()
Thorsten
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.