45  ディレクトリの操作

この章では、ディレクトリ(フォルダー)の作成、操作、保存、インポートに関する一般的なシナリオを説明します。

45.1 準備

fs パッケージ

fs パッケージは、R の base パッケージ(以下 base R)関数のいくつかを改良し、ディレクトリの操作を簡単にし tidyverse パッケージの一部です。以下のセクションでは、しばしば fs パッケージからの関数を使用します。

pacman::p_load(
  fs,             # ファイル、ディレクトリの操作
  rio,            # インポート・エクスポート
  here,           # 相対ファイルパス
  tidyverse)      # データの管理と可視化

ディレクトリをデンドログラムツリーで表示する

fs パッケージの dir_tree() 関数を使用します。

path = にフォルダのファイルパスを指定し、1つの階層のみを表示するか(recurse = FALSE オプション)、全てのサブディレクトリの全てのファイルを表示するか(recurse = TRUE オプション)を指定します。 以下では、here() を R プロジェクトの略称として使用し、そのサブフォルダの “data” を指定しています。“data” には、この R ハンドブックで使用するすべてのデータが格納されています。 “data” とそのサブフォルダ内のすべてのファイルを表示するように設定します。(“cache”, “epidemic models”, “population”, “shp”, “weather” など).

fs::dir_tree(path = here("data"), recurse = TRUE)
C:/Users/ngulu864/AppData/Local/Temp/RtmpyIElas/file7c74172e15e5/data
├── africa_countries.geo.json
├── cache
│   └── epidemic_models
│       ├── 2015-04-30
│       │   ├── estimated_reported_cases_samples.rds
│       │   ├── estimate_samples.rds
│       │   ├── latest_date.rds
│       │   ├── reported_cases.rds
│       │   ├── summarised_estimated_reported_cases.rds
│       │   ├── summarised_estimates.rds
│       │   └── summary.rds
│       ├── epinow_res.rds
│       ├── epinow_res_small.rds
│       ├── generation_time.rds
│       └── incubation_period.rds
├── case_linelists
│   ├── cleaning_dict.csv
│   ├── fluH7N9_China_2013.csv
│   ├── linelist_cleaned.rds
│   ├── linelist_cleaned.xlsx
│   └── linelist_raw.xlsx
├── country_demographics.csv
├── covid_example_data
│   ├── covid_example_data.xlsx
│   └── covid_shapefile
│       ├── FultonCountyZipCodes.cpg
│       ├── FultonCountyZipCodes.dbf
│       ├── FultonCountyZipCodes.prj
│       ├── FultonCountyZipCodes.sbn
│       ├── FultonCountyZipCodes.sbx
│       ├── FultonCountyZipCodes.shp
│       ├── FultonCountyZipCodes.shp.xml
│       └── FultonCountyZipCodes.shx
├── covid_incidence.csv
├── covid_incidence_map.R
├── district_count_data.xlsx
├── example
│   ├── Central Hospital.csv
│   ├── district_weekly_count_data.xlsx
│   ├── fluH7N9_China_2013.csv
│   ├── hospital_linelists.xlsx
│   ├── linelists
│   │   ├── 20201007linelist.csv
│   │   ├── case_linelist20201006.csv
│   │   ├── case_linelist_2020-10-02.csv
│   │   ├── case_linelist_2020-10-03.csv
│   │   ├── case_linelist_2020-10-04.csv
│   │   ├── case_linelist_2020-10-05.csv
│   │   └── case_linelist_2020-10-08.xlsx
│   ├── Military Hospital.csv
│   ├── Missing.csv
│   ├── Other.csv
│   ├── Port Hospital.csv
│   └── St. Mark's Maternity Hospital (SMMH).csv
├── facility_count_data.rds
├── flexdashboard
│   ├── outbreak_dashboard.html
│   ├── outbreak_dashboard.Rmd
│   ├── outbreak_dashboard_shiny.Rmd
│   ├── outbreak_dashboard_test.html
│   └── outbreak_dashboard_test.Rmd
├── fluH7N9_China_2013.csv
├── gis
│   ├── africa_countries.geo.json
│   ├── covid_incidence.csv
│   ├── covid_incidence_map.R
│   ├── linelist_cleaned_with_adm3.rds
│   ├── population
│   │   ├── sle_admpop_adm3_2020.csv
│   │   └── sle_population_statistics_sierraleone_2020.xlsx
│   └── shp
│       ├── README.txt
│       ├── sle_adm3.CPG
│       ├── sle_adm3.dbf
│       ├── sle_adm3.prj
│       ├── sle_adm3.sbn
│       ├── sle_adm3.sbx
│       ├── sle_adm3.shp
│       ├── sle_adm3.shp.xml
│       ├── sle_adm3.shx
│       ├── sle_hf.CPG
│       ├── sle_hf.dbf
│       ├── sle_hf.prj
│       ├── sle_hf.sbn
│       ├── sle_hf.sbx
│       ├── sle_hf.shp
│       └── sle_hf.shx
├── godata
│   ├── cases_clean.rds
│   ├── contacts_clean.rds
│   ├── followups_clean.rds
│   └── relationships_clean.rds
├── likert_data.csv
├── linelist_cleaned.rds
├── linelist_cleaned.xlsx
├── linelist_raw.xlsx
├── make_evd_dataset-DESKTOP-JIEUMMI.R
├── make_evd_dataset.R
├── malaria_app
│   ├── app.R
│   ├── data
│   │   └── facility_count_data.rds
│   ├── funcs
│   │   └── plot_epicurve.R
│   ├── global.R
│   ├── malaria_app.Rproj
│   ├── server.R
│   └── ui.R
├── malaria_facility_count_data.rds
├── phylo
│   ├── sample_data_Shigella_tree.csv
│   ├── Shigella_subtree_2.nwk
│   ├── Shigella_subtree_2.txt
│   └── Shigella_tree.txt
├── rmarkdown
│   ├── outbreak_report.docx
│   ├── outbreak_report.html
│   ├── outbreak_report.pdf
│   ├── outbreak_report.pptx
│   ├── outbreak_report.Rmd
│   ├── report_tabbed_example.html
│   └── report_tabbed_example.Rmd
├── standardization
│   ├── country_demographics.csv
│   ├── country_demographics_2.csv
│   ├── deaths_countryA.csv
│   ├── deaths_countryB.csv
│   └── world_standard_population_by_sex.csv
├── surveys
│   ├── population.xlsx
│   ├── survey_data.xlsx
│   └── survey_dict.xlsx
└── time_series
    ├── campylobacter_germany.xlsx
    └── weather
        ├── germany_weather2002.nc
        ├── germany_weather2003.nc
        ├── germany_weather2004.nc
        ├── germany_weather2005.nc
        ├── germany_weather2006.nc
        ├── germany_weather2007.nc
        ├── germany_weather2008.nc
        ├── germany_weather2009.nc
        ├── germany_weather2010.nc
        └── germany_weather2011.nc

45.2 ディレクトリ内のファイルを一覧表示する

ディレクトリ内のファイル名だけをリストアップするには、base R の dir() を使用します。 例えば、下記のコマンドは R プロジェクトの “data” フォルダの “population” サブフォルダ内のファイル名をリストアップしています。相対的なファイルパスは here() を使ってえられます (詳しくは データのインポート・エクスポート 章を参照してください)。

# ファイル名
dir(here("data", "gis", "population"))
[1] "sle_admpop_adm3_2020.csv"                       
[2] "sle_population_statistics_sierraleone_2020.xlsx"

ディレクトリのファイルのフルパスをリストアップするには、fs パッケージの dir_ls() を使用できます。 base R を使う場合は list.files() です。

# ファイルパス
dir_ls(here("data", "gis", "population"))
C:/Users/ngulu864/AppData/Local/Temp/RtmpyIElas/file7c74172e15e5/data/gis/population/sle_admpop_adm3_2020.csv
C:/Users/ngulu864/AppData/Local/Temp/RtmpyIElas/file7c74172e15e5/data/gis/population/sle_population_statistics_sierraleone_2020.xlsx

ディレクトリ内の各ファイルに関するすべてのメタデータ情報(パス、更新日など)を得るには、 fs パッケージの dir_info() を使用します。

これは、ファイルの最終更新時刻を抽出したい場合、例えば、最新バージョンのファイルをインポートしたい場合などに特に有効です。この例については、データのインポート・エクスポート の章を参照してください。

# ファイル情報
dir_info(here("data", "gis", "population"))

以下は、関数から返されたデータフレームです。すべての列を見るには右にスクロールしてください。

45.3 ファイルの情報

特定のファイルに関するメタデータ情報を抽出するには,fs パッケージの file_info() (または base R の file.info()) を使用します。

file_info(here("data", "case_linelists", "linelist_cleaned.rds"))

ここでは、$ を使って結果のインデックスを指定し、modification_time の値のみを返すようにしています。

file_info(here("data", "case_linelists", "linelist_cleaned.rds"))$modification_time
[1] "2024-02-18 14:56:16 CET"

45.4 存在するか確認する

R オブジェクト

R オブジェクトが R の中に存在するかどうかを調べるには、base R の exists() を使用します(オブジェクト名を引用符で囲み渡してください)。

exists("linelist")
[1] FALSE

base R パッケージの中には、“data” のような一般的なオブジェクト名を裏で使用しているものがあり、そういったオブジェクトは inherit = FALSE が指定されない限り、TRUE として表示されることに注意してください。これが、データセットに “data” という名前をつけない理由の 1 つです。

exists("data")
[1] TRUE
exists("data", inherit = FALSE)
[1] FALSE

関数を書く場合、引数として渡した値が存在するかどうかを調べるには exists() ではなく、 base R の missing() を使うべきです。

ディレクトリ

ディレクトリが存在するかどうかを調べるには,fs パッケージの is_dir() にファイルパス(とファイル名)を与えてください.右にスクロールすると TRUE が表示されていることがわかります。

is_dir(here("data"))
C:/Users/ngulu864/AppData/Local/Temp/RtmpyIElas/file7c74172e15e5/data 
                                                                 TRUE 

代替としては、base R の file.exists() があります。

ファイル

特定のファイルが存在するかどうかを調べるには、fs パッケージの is_file() を使用します。下記の関数の結果を右にスクロールすると TRUE が表示されることがわかります。

is_file(here("data", "case_linelists", "linelist_cleaned.rds"))
C:/Users/ngulu864/AppData/Local/Temp/RtmpyIElas/file7c74172e15e5/data/case_linelists/linelist_cleaned.rds 
                                                                                                     TRUE 

base R での代替は file.exists() です。

45.5 作成

ディレクトリ

新しいディレクトリ(フォルダ)を作成するには、fs パッケージの dir_create() を使用します。すでにディレクトリが存在する場合は、上書きされず、エラーも返されません。

dir_create(here("data", "test"))

代替として、base R の dir.create() があります。これはディレクトリがすでに存在する場合はエラーを表示します。一方、dir_create() はエラーを返しません。

ファイル

空のファイルは fs パッケージの file_create() で作成できます。ファイルがすでに存在する場合は、上書きされたり変更されたりすることはありません。

file_create(here("data", "test.rds"))

base R での代替手段は file.create() です。しかし、ファイルがすでに存在する場合、この代替手段はファイルを削除します。file_create() を使用すれば、ファイルは変更されずに残ります。

存在しない場合にのみ作成する

作成中

45.6 削除

R オブジェクト

R オブジェクトを削除するには、base R の rm() を使用します。

ディレクトリ

fs パッケージの dir_delete() を使用します。

ファイル

fs パッケージの file_delete() でファイルを削除できます。

45.7 他のファイルを実行する

source()

ある R スクリプトを別の R スクリプト中から実行する場合、base R の source() コマンドを使用できます。

source(here("scripts", "cleaning_scripts", "clean_testing_data.R"))

以下は、上記の R スクリプトを表示し、スクリプトの右上にある “Source” ボタンをクリックすることと同じです。これはスクリプトを実行しますが、特に意図しない限り出力なく実行されます(R コンソールへの出力はありません)。[Interactive console] の章で、source() を使って R コンソールでユーザーと対話する例を参照してください。

render()

render()source() のバリエーションで、R markdown のスクリプトで最もよく使用されます。R markdown ファイルを input = に指定し、output_format = (典型的には “html_document”、“pdf_document”、“word_document”、“” のいずれか) を指定します。

詳しくは R Markdown で作るレポート をご覧ください。また render() のドキュメントをこちらから、もしくは ?render と入力して参照してください。

ディレクトリ内のファイルを実行する

for ループ を作成し、それを使って dir() で識別されるディレクトリ内のすべてのファイルを source() できます。

for(script in dir(here("scripts"), pattern = ".R$")) {   # R プロジェクトの "scripts" フォルダにある各スクリプト名(拡張子 .R)に対して
  source(here("scripts", script))                        # scripts フォルダに存在する、同じ名前のファイルをソースとする
}

特定のスクリプトだけを実行したい場合は、次のように名前で識別できます。

scripts_to_run <- c(
     "epicurves.R",
     "demographic_tables.R",
     "survival_curves.R"
)

for(script in scripts_to_run) {
  source(here("scripts", script))
}

こちらは fs パッケージの関数と base R 関数の比較です。

ディレクトリ内のファイルをインポートする

個別のファイルのインポートとエクスポートについては、データのインポート・エクスポート の章をご覧ください。

また、ファイル名に含まれる日付をもとに、またはファイルのメタデータを見て、自動的に最新のファイルをインポートする方法についても データのインポート・エクスポート の章を参照してください。

purrr パッケージによるデモの例については、ループと反復処理・リストの操作 の章を参照してください:

  • データフレームを分割し、複数の CSV ファイルとして保存する
  • データフレームを分割し、1つの Excel ワークブック内で各パーツを別のシートとして保存する
  • 複数の CSV ファイルを取り込み、1 つのデータフレームにまとめる
  • 複数のシートを持つ Excel ワークブックをインポートして、1 つのデータフレームにまとめる

45.8 base R

以下の list.files()dir() 関数をご覧ください。これらは指定したディレクトリ内のファイルをリストアップするという同じ操作を行います。 ignore.case = や検索する特定のパターンを指定できます。

list.files(path = here("data"))

list.files(path = here("data"), pattern = ".csv")
# dir(path = here("data"), pattern = ".csv")

list.files(path = here("data"), pattern = "evd", ignore.case = TRUE)

現在「開いている」ファイルは、「~$hospital_linelists.xlsx」のように、先頭にチルダを付けてフォルダ内に表示されます。

45.9 参考資料

https://cran.r-project.org/web/packages/fs/vignettes/function-comparisons.html