All Articles
    Search by

    [初心者向けR講座]今更聞けない! Rにおける”関数”って何? 今からプログラミングを始める人にも分かるように説明します!

    はじめに

    こんにちは! 今回はRを学び始めた人向けに、“関数”とは何なのか?を説明したいと思います!👐

    このブログではRの良さを初心者にも分かるように伝えたい、というモチベーションで始めましたが、正直初心者の立場に立てていなかったと非常に反省しています(突然の謝罪)
    というのも、最近会社で本格的にRのレクチャーを始めたのですが、意外にもR解析における関数が何なのか?ということが知られていないことが分かりました🤔。R解析は極論、関数を組み合わせるだけで八割方の解析ができます。そのため、関数は極めて重要な考え方になります。

    たまたまこのブログに流れ着いた方、是非この記事で関数について理解を深めていってくださいー!🛀

    視覚的に関数を理解する

    イメージは高校数学の関数に近い

    y=f(x)

    “ワイ イコール エフエックス”👩‍🏫

    おそらく、「三角関数なんか忘れちまったよ」という人でも関数は聞き覚えがあるのではないでしょうか。

    数学における関数は一言で言えば、「xを関数fに入れると、yが返ってくる」というものでしたね。Rに限らず、プログラミングでも同じです。何かを入れると、何かが返ってくるのです。

    関数は自販機🍼

    私が中学の時に習ったたとえ話でいうと、関数は自販機です。
    硬貨(コイン)💰を入れて、オプション🔘を選び、何かのドリンク🎍が結果として得られます。

    2 800x450

    関数の本体は自販機の中身そのもの、ということになりますが、自販機がどういう原理で動いているか説明できますか?できませんよね。というか世の中のほとんどの人は説明する必要がないですよね。 お金を入れて、欲しい商品を選ぶ。これだけ知っていればよいのです。

    R解析でも同じですよく使う関数だけ、なんとなく使い方を覚えていきましょう。なんとなくていいんですよ。

    関数をつかう

    用語説明

    さて、今のところイメージで説明しましたが関数についてなんとなく分かっていただけましたか?
    ここからはもう少し技術ブログっぽく、Rにおける関数の説明をしていきますね。

    どのプログラミング言語でも共通の用語ですが、関数における入力を「引数(ひきすう)」、返ってくる値のことを「返り値(かえりち)」とか「戻り値(もどりち)」などと呼びます。

    3 800x450

    用例はこんな感じでしょうか。

    「この関数は~~を引数として与えると**が戻り値として返ってきます。」
    「この関数は第一引数が~~で、第二引数が~~なのか!」
    「この関数の戻り値はデータフレーム型として返ってくるんだね~。」

    このブログにおいても引数、戻り値という独特な呼び方を沢山することになるので、この用語だけは是非覚えておいてください・・・!

    実例

    では実際に関数を見てみましょう。

    Rでは組み込み関数のread.csv()という関数があります。文字通り、csvファイルを読み込む関数ですね。関数の説明はhelp()関数に関数名を引数として与えるか、あるいは?をつけるだけでも見ることができます。

    help(read.csv)
    ?read.csv

    すると上の方にこのようなものが出てきます。

    read.csv(file, header = TRUE, sep = ",", quote = "\"",
             dec = ".", fill = TRUE, comment.char = "", ...)

    このfileとかheadersepquotedecfillcomment.charなどというのがread.csvの引数です。 引数の名前・順番には特段決まったルールはありません。パッケージの思想だったり、その関数を定義した人の気分だったりで決まっているものです。

    ちゃんとしたパッケージ ({dplyr}など)であれば統一感があったりしますが、そうでないこともしばしば。分からなくなったら都度関数のヘルプを確認する癖をつけましょう!ℹ️

    引数名の指定はした方がベター

    たとえば、先ほどのread.csvだと指定できる引数が沢山ありますよね。これを指定したいときには、「この引数には」「これを代入する」という関係性を明示した方がベターです。

    read.csv(file = "/home/file.csv", header = FALSE, sep = "\t", fill = FALSE)

    これを明示するメリットは以下の二つです。

    • 引数指定の順番を気にしなくていい
    • 間違い(バグ)が起きにくい

    プログラミングではいかにバグが起きないように慎重にことを進めるかが技量に直結してきますので、後者はとても重要なメリットです。

    ちなみに、引数名を指定しなかった場合には指定した順番で判断されます。

    read.csv("/home/file.csv", FALSE, "\t", "'")

    引数オプションを複数指定する場合、引数名を書かないと上の例のように何に何を指定してるのか意味不明になりがちです。このような場合にはめんどくさがらずに引数名をきちんと指定してあげましょう。

    たまに引数がワケワカランこともある

    read.csvのヘルプには下の方にちょこんと書かれた引数として、悪名高きstringAsFactorがあります。 あまりに有名なトラップなので知ってる方も多いと思いますが、この関数を使うときはこの引数オプションにFLASEを与えなければならないケースがほとんどです🤔。

    read.csv("filename.csv", stringsAsFactors = FALSE)

    この関数はデフォルトだとstringAsFactors = TRUEという値が入っているために、必ず文字列がfactor型になってしまいます。factor型はちょっと特殊な型なので、エラーの原因になることが非常に多いわけです。

    read.csv()関数は組み込み関数(最初からインストールされている関数のこと)の一つですが、このような感じでめちゃめちゃ不便な仕様になっていることも組み込み関数にはよくある話です

    Snitch

    Snitch

    今年のアップデート(R=4.2.0)で遂にすべての関数でstringAsFactorsがFALSEに切り替わる、ということで非常に話題になりました。

    ちなみにですが、read.csv()はこうした理由からほとんど使う人はいません。上位互換関数のreadr::read_csv()readr::read_tsv()を使うようにしましょう。 以前紹介したvroom::vroom()も速くて使いやすいオススメ関数です!

    関数のデフォルト値

    関数によっては、デフォルト値が設定されている場合があります。

    たとえば今紹介した完全上位互換関数のread_csv()のヘルプを見てみましょう。

    ?readr::read_csv
    read_csv(
      file,
      col_names = TRUE,
      col_types = NULL,
      col_select = NULL,
      id = NULL,
      locale = default_locale(),
      na = c("", "NA"),
      quoted_na = TRUE,
      quote = "\"",
      comment = "",
      trim_ws = TRUE,
      skip = 0,
      n_max = Inf,
      guess_max = min(1000, n_max),
      name_repair = "unique",
      num_threads = readr_threads(),
      progress = show_progress(),
      show_col_types = should_show_types(),
      skip_empty_rows = TRUE,
      lazy = should_read_lazy()
    )

    Snitch

    Snitch

    さすがHadley Wickhamさんの息がかかったtidyverse系パッケージ。組み込み関数とは違ってヘルプが見やすいです。

    この関数のヘルプ文を見ると

    引数名 = 値

    という形式になっていることが分かります。この値がデフォルト値です。

    デフォルト値はつまり、指定をしなくても勝手に入る値のことです。逆に、デフォルト値が指定されていない引数(ここではfileだけ)は必ず指定をする必要があります。

    read_csv(col_names = TRUE)
    # エラーになる
    # Error in vroom::vroom(file, delim = ",", col_names = col_names, col_types = col_types, :  引数 "file" がありませんし、省略時既定値もありません 

    自分で関数を作る

    一通り関数の仕組みを理解したところで、自作関数についても軽く知っていきましょう。いろんな人が作成した便利な関数と同じように、自分でも関数を作ることができます。これを、「関数を定義する」といったりします👨‍🏫

    関数の定義は以下のようにします。

    my_funciton <- function(引数){
      # 引数を使った処理
      引数 + 1
    }

    function(){}を何かの変数名に代入するだけです。試しに上で定義した関数を使ってみます。

    my_funciton(10)
    # [1] 11

    ちゃんと10+1が計算されました!

    関数の定義では、冒頭のread.csvread_csvと同じように複数の引数を設定したり、デフォルト値を設定することも可能です。

    my_second_func <- function(today, value = 100, message = NA) {
      paste0("[", today, "] ", "{", value, "}", "-", message)
    }
    
    my_second_func(today = "4/22")
    # [1] "[4/22] {100}-NA"
    my_second_func(today = "4/23", message = "Error!")
    # [1] "[4/23] {100}-Error!"
    my_second_func(today = "4/24", message = "Warning?", value = 111111111)
    # [1] "[4/24] {111111111}-Warning?"

    まとめ

    ということで、今回はRプログラミングにおける関数の意味や使い方について解説しました!

    R解析に慣れた人にとっては簡単すぎる内容だったかもしれませんが、少しでも初心者の方に刺さってくれたらうれしいです・・・!

    今回の内容はこんな感じでしたー!

    • 関数は使い方を知っておけばとりあえずおk
    • 関数名(引数) -> 戻り値(返り値)
    • 引数にはデフォルト値が設定されている場合がある
    • 引数を複数指定する際には引数名=を明示する
    • 引数名を書かないと、順番が評価される
    • 自分で関数を作ることもできる

    それではまた!

    Published Apr 22, 2022

    © 2020-2024 Hiroyuki Odake