Help us understand the problem. What is going on with this article?

Rで一時ファイルの利用

More than 3 years have passed since last update.

ちょいちょい忘れては調べることになるのでメモ。

一時ファイル

一時ファイルとは一時的なデータを保持しておくファイルで、通常さくっと作られて用が済めば削除されるものです。Rでも自分で準備して利用することが可能で、ちょっとデータなどを預けておいたりするのに重宝します。今回はこれの基本的なところを確認。

tempfile関数とtempdir関数

Rの場合、作成した一時ファイルは一時ディレクトリに置かれます。そしてこの一時ディレクトリはそのRsessinoで準備されています。その一時ディレクトリへのパスを取得する関数がtempdir()です:

tempdir()
#>  [1] "/tmp/RtmpLapPwK"

ルートからのパスはOSや環境に依存しますが、一時ディレクトリ名はRtmp*という名前になるようです。

では今度は一時ファイルを作成してみたいと思います。一時ファイルを作成する関数はtempfile()関数です:

tempfile()
#>  [1] "/tmp/RtmpLapPwK/file9403432469"

上のtempdir()で出てきたディレクトリにfile*というファイルが作成されて、そのファイルへのパスが返ってきます。通常はこのようにするのではなく、返り値をオブジェクトに預けます:

tmpf <- tempfile()
tmpf
#>  [1] "/tmp/RtmpLapPwK/file940709780f0"
class(tmpf)
#>  [1] "character"

このように預けておくと、このパスを利用してファイル操作ができるようになります:

kosaki <- c("kosaki", "yappari", "saikou!")
writeLines(kosaki, tmpf)
readLines(tmpf)
#>  [1] "kosaki"  "yappari" "saikou!"

Usage

tempdir()関数には引数はありません。単に一時ディレクトリのパスを返すのみです。tempfile()のUsageは以下のとおりです:

tempfile(pattern = "file", tmpdir = tempdir(), fileext = "")
  • pattern
    • 空ではない文字列ベクトルを指定
    • 一時ファイル名の最初の部分がこれになります
    • 初期値は"file"なので、上述のようにfile*という名に
  • tmpdir
    • 空ではない文字列ベクトルを指定
    • 一時ファイルを設置するディレクトリ名を指定
    • 初期値はtempdir()であり、上述した一時ディレクトリに格納される
  • fileexit
    • 空ではない文字列ベクトルを指定
    • 一時ファイルの拡張子を設定
    • 初期値は空の文字列で、つまりは拡張子なしのファイル

ということで、内容はシンプルです。ポイントは以下のようなところ:

  • 文字列ベクトルを受け付ける、すなわち一度にたくさん作れる
  • 一時ファイル名でもpatternである程度は付与できる
  • .csv.txt、あるいは.html.mdなどいろいろできる

いろいろ試してみる

てことで遊んでみます。まずは複数作成。

tempfs <- tempfile(paste("kosaki", 1:3, sep = "_"))
tempfs
#>  [1] "/tmp/RtmpLapPwK/kosaki_194012d6e993"
#>  [2] "/tmp/RtmpLapPwK/kosaki_2940a2bce14" 
#>  [3] "/tmp/RtmpLapPwK/kosaki_394076b5137c"

文字列ベクトルで与えると、それに合わせて準備してくれました。

次はいろんな拡張子を与えてみます:

tempfs <- tempfile("kosaki", fileext = c("", ".txt", ".csv", ".html"))
tempfs
#>  [1] "/tmp/RtmpLapPwK/kosaki9407c1cc7d4"     
#>  [2] "/tmp/RtmpLapPwK/kosaki9401f98b725.txt" 
#>  [3] "/tmp/RtmpLapPwK/kosaki9403cda92a8.csv" 
#>  [4] "/tmp/RtmpLapPwK/kosaki940179b1fe6.html"

こんな感じですね。実用性はほぼ無いですがテストしました。

では、ちょっと長いですが応用です:

# 前準備: 独自でRコードをマークアップした文字列を準備
hoge <- paste(
  "最初",
  "<s>",
  "paste('kosaki', 'No.1')",
  "<e>",
  "終わり",
  "",
  sep = "\n"
)

# 手順1: ターゲットを一時ファイルへ格納
tmp <- tempfile(fileext = c(".txt", ".R"))
write(hoge, tmp[1])

# 手順2: 一時ファイルから文字列ベクトルとして読みだす
xx <- readLines(tmp[1])

# 手順3: 読みだした文字列ベクトルからRコードの位置を特定して一時ファイル(.R)へ
chunk_start <- grep("<s>", xx)
chunk_end <- grep("<e>", xx)
r_chunk <- xx[chunk_start:chunk_end]
r_code <- r_chunk[!grepl("<s>|<e>", r_chunk)]
write(r_code, file = tmp[2])

# 手順4: 一時ファイルのコードを評価
out <- eval(parse(tmp[2]))

# 手順5: 出力を元のテキストに埋め込む

finish <- c(
  xx[1:chunk_end],
  "<out_s>",
  print(out),
  "<out_e>",
  xx[(chunk_end + 1):length(xx)]
)

# 手順6: ファイルとして出力
write(paste(finish, collapse = "\n"), file = "output.txt")
file.copy(paste(tmp[2], collapse = "\n"), "r_code.R")

伝わる人には伝わると思いますが、これはknitをイメージした処理です。実際の処理はもっと細やかにやるものなのですが、あくまで一時ファイルを使った例なのでざっくりやりました。

この一時ファイルはいろんなところで使われていて、パッケージの関数内処理で作成しているとかよく見かけます。ぜひ活用してみてください。

Enjoy!

kazutan
ただの残念なぞうさんです。同名のTwitterアカウントでほそぼそと。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away