多変量解析_02_データの読み込み・基本操作

2K Views

July 25, 23

スライド概要

神戸大学経営学研究科で2022年度より担当している「統計的方法論特殊研究(多変量解析)」の講義資料「02_データの読み込み・基本操作」です。
2025/2/5: 全体的に内容に手を入れました。RmarkdownからQuartoに変更しました。

profile-image

神戸大学経営学研究科准教授 分寺杏介(ぶんじ・きょうすけ)です。 主に心理学的な測定・教育測定に関する研究を行っています。 講義資料や学会発表のスライドを公開していきます。 ※スライドに誤りを見つけた方は,炎上させずにこっそりお伝えいただけると幸いです。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Chapter 2 データの読み込み・基本操作 Chapter 2 データの読み込み・基本操作 R によるデータの読み込みと,この後の内容で必要になるデータフレームの基本操作を一通り説 明しています。 本資料は,神戸大学経営学研究科で 2022 年度より担当している「統計的方法論特殊研究(多 変量解析) 」の講義資料です。CC BY-NC 4.0 ライセンスの下に提供されています。 作成者連絡先 神戸大学大学院経営学研究科 分寺杏介(ぶんじ・きょうすけ) mail: [email protected] website: https://www2.kobe-u.ac.jp/~bunji/ さっそく R を使ったデータ分析の演習に突入します*1 。本講義のメインである因子分析など の分析法に入る前に,今回はデータの読み込みを行い,R の基本操作を説明しながらデータの確 認&ミスの処理を行っていきます。次回以降では引き続き,データの前処理(ゴミデータの処理) および項目・尺度の性質(分布・信頼性・妥当性など)をチェックしておきます。 ディレクトリの話 本講義では,特に断りがない限りコードやデータなどは全てワーキングディレクトリに置かれ ている前提でコードを示します。 (↑この意味がわかった人はこのセクションは読み飛ばして OK です。Section 2.1 に入るまで 休憩しててください。 ) パ ソ コ ン で は, 全 て の フ ァ イ ル は ど こ か し ら の デ ィ レ ク ト リ (directory) に 置 か れ る ことになります。いわゆる「フォルダ」というものも,一つのディレクトリを表したもの *1 本講義では,なるべく tidyverse 的な記法は使用せず,R デフォルトの記法で示すようにします。tidyverse 的な記法に慣れている方は適宜脳内変換してください。 1

2.

Chapter 2 データの読み込み・基本操作 と考えることが出来ます。ディレクトリはファイルの「住所」のようなもので,例えば私 (Bunji) の Windows のデスクトップに hogehoge.xlsx という Excel ファイルが置かれて いたとすると,実際には C:/Users/Bunji/Desktop/hogehoge.xlsx という位置づけになっ ています*2 。つまり,例えば Excel などで hogehoge.xlsx を開こうとした場合,厳密には 「 C:/Users/Bunji/Desktop/hogehoge.xlsx を開け」という指示が出されているわけです。 ち な み に デ ィ レ ク ト リ は ス ラ ッ シ ュ ( /) で 階 層 構 造 を 表 し て い ま す。 つ ま り 先 程 の hogehoge.xlsx は C: の中の Users フォルダの中の Bunji フォルダの中の Desktop フォ ルダの中にある,ということが示されています。 INFO 補足:スラッシュとバックスラッシュ 【結論を先にいうと】スラッシュ( /)の代わりにバックスラッシュ( \)を使う場合は,2 つ連続して使用( \\)してください。 階層構造を表す記号として,スラッシュ( /)の代わりにバックスラッシュ( \)や¥マー クが使われることもあります。 ただし,実はバックスラッシュと¥マークは本質的には同じ意味を持っています。たぶん パソコンの環境や使用するソフトウェアによっては,キーボードの¥マークが書かれた キーを押してもバックスラッシュが表示されたりするでしょう。 そしてディレクトリの階層構造を表す場合,スラッシュでもバックスラッシュでもどちら でも良いのですが,バックスラッシュをする場合,プログラミング言語には「エスケープ シーケンス」と呼ばれるちょっと厄介な事情があります。プログラミング言語の多くでは 文字列を扱うことができますが,文字列には「文字で表せない文字」とでも呼べるような 存在があります。例えば改行なんかがその代表例です。改行を含む以下の文字列を考えて みます。 I am happy. 当然改行自体は文字として表せないのですが,プログラミング言語の中で扱うためには改 行も含めて一つの「文字列」として扱わないと,改行の無い”I am happy.” と区別ができな くなってしまいます。そこで多くのプログラミング言語では,このような「文字で表せな い文字」を表す特殊な文字が用意されています。例えば改行を表す特殊文字は \n(バック スラッシュ+ n)です。したがって,改行ありは "I am \nhappy."と表すことで,改行な し( "I am happy.")と区別ができるわけです。ちなみに R では cat() 関数を使うと, 特殊文字を変換した後の文字列を表示することができます。 *2 反対に,私の研究室にある書類をディレクトリ的に書くならば「兵庫県/神戸市/灘区/六甲台町/2/1/神戸大学/ 第 4 学舎/512/※※に関する書類」という感じになるわけです。郵便番号は「兵庫県/神戸市/灘区/六甲台町」 というフォルダにつけられたニックネーム的なものということですね。 2

3.

Chapter 2 データの読み込み・基本操作 ここでの問題は,バックスラッシュが通常は「次の文字が特殊文字であることを表すため の記号」として扱われるということです。ではここで,先程出てきたディレクトリをバッ クスラッシュに置き換えたバージョンを見てみます。 C:\Users\Bunji\Desktop\hogehoge.xlsx このとき,ディレクトリを前から順に解釈しようとすると,\が登場した瞬間に「次に来る 文字は特殊文字を表しているな」と解釈しようとします。したがって,\U や \B といった 特殊文字として解釈しようとするわけです。そしてそんな特殊文字は R には用意されてい ません。そんなわけで,/と \の違いによって • C:/Users/Bunji/Desktop/hogehoge.xlsx を開け→問題なく開ける • C:\Users\Bunji\Desktop\hogehoge.xlsx を開け→「 \U なんて特殊文字は無 い」とエラーが出る というように結果に違いが出てしまいます。このエラーを避けるためには, 「この \は特殊 文字を表すバックスラッシュではなくただのバックスラッシュである」ということを示す ために「バックスラッシュを表す特殊文字」を使います。具体的には,バックスラッシュ を 2 つ重ねた \\が「ただの文字としてのバックスラッシュ」を表すので, • C:\\Users\\Bunji\\Desktop\\hogehoge.xlsx を開け という指示であればスラッシュのときと同じように機能してくれるわけです。 「ファイルを開く」ときの指定方法はもちろん R でも同じです。つまり R で hogehoge.xlsx を開こうとした場合,通常は「 C:/Users/Bunji/Desktop/hogehoge.xlsx を開け」という 指示を出す必要があります。ですが, R を始めとするプログラミング言語(というかほとん どのプログラム)では,ファイルの位置を相対的なものとしても考えることができます。その 時の基準となるディレクトリのことを, R ではワーキングディレクトリと呼んでいます。例 えばいま,ワーキングディレクトリが C:/Users/Bunji/Desktop/に設定されているとしま す。このとき,hogehoge.xlsx というファイルを読もうとすると,「 (このディレクトリにある) hogehoge.xlsx を開け」だけで通じるようになるのです。もう少し正確に言うと「 C:/から始 まる絶対パスが指定されている場合にはそのファイルを,そうではなく相対パスが指定されてい る場合には,ワーキングディレクトリ内のそのファイルを開け」という感じになっており,ファ イルの指定方法は 2 種類ある,ということになります。 R で現在のワーキングディレクトリを確認および変更する方法はそれぞれ以下のとおりです。 ワーキングディレクトリの確認 1 getwd() 3

4.

Chapter 2 データの読み込み・基本操作 ワーキングディレクトリの変更 1 2 3 4 5 6 7 8 9 10 11 # C:/Users/Bunji/Desktop/に変更したいとすると setwd("C:/Users/Bunji/Desktop/") # ワーキングディレクトリ自体も相対パスで指定可能 # もとのワーキングディレクトリが"C:/Users/Bunji/"だったら setwd("Desktop") # もとのワーキングディレクトリが"C:/Users/Bunji/Document"だったら setwd("../Desktop") # "../"はワーキングディレクトリの一個上の階層を指す たぶん.R ファイルなどをクリックして Rstudio を開いた場合,デフォルトでは「起動時のワー キングディレクトリはその.R ファイルなどがある場所」になると思います。この先で「あるはず のファイルが読み込めない」という事態に陥った場合は,まず getwd() でワーキングディレク トリの設定を確認し,必要に応じて setwd() で変更してください。 ということで,この講義で使用するファイル一式を格納するフォルダを用意しておき,使用す るデータやこの先作成するコードは全てそのフォルダ内に入れるようにしておきましょう。そし て,ワーキングディレクトリとしてそのフォルダを指定するようにしましょう。 プロジェクト …と,ここまでの話がよくわからなかった人も安心してください。Rstudio にはそういった 面倒事を避けるための機能としてプロジェクト(Project)というものが用意されています。 Rstudio を用いて分析を行う場合には,とりあえず何も考えずにプロジェクトを作成するクセを 付けておくと良いかもしれません。 プロジェクト作成の手順 RStudio のプロジェクトは,半透明の立方体に R と書かれたアイコン(図 2.1)で表されます。 まずは RStudio のたぶん左上の方にあるこのアイコンを探してください。 図 2.1: Project のアイコン あるいは「File > New Project」でも構いません。 続いて,プロジェクト用フォルダをどこに作成するかを決めます。図 2.4 には “New Directory” と “Existing Directory”,あと一つなんかありますが,とりあえず上の 2 つのいずれかから選び 4

5.

Chapter 2 データの読み込み・基本操作 図 2.2: Project の新規作成 図 2.3: Project の新規作成 ましょう。 New Directory 新しくフォルダを作成して,そこをプロジェクト用フォルダとする。これから 作業を始めるのでまだデータを置く場所も何も決まっていない場合はこちら。 Existing Directory 既存のフォルダをプロジェクト用フォルダとして利用する。すでにデータや 原稿などを一つのフォルダにまとめていて,そのフォルダに R のコードも一緒に置いてお きたい場合はこちら。 “New Directory” を選んだ場合 いろいろな”Project Type” から一つ選べと言われます(図 2.5)。R を使いこなせるようにな ると,R を使って本を書いたり(Quarto や bookdown) ,自分でパッケージを作れるようにな るので,それ用の設定が色々と用意されているわけですが,単純に分析だけする場合には一番上 の”New Project” を選べば OK です。 あとは新規プロジェクトフォルダの作成場所を決めるだけです。“Directory name” にはプロ ジェクトの名前を(自分でその意味がわかるようにしておけば OK) ,“Create project …” には どこのフォルダにそのプロジェクトを置くかを指定してあげます。つまり 図 2.6 のように指定 した場合には,C:/Users/Kyosuke Bunji/Desktop に stat_Thu2 というフォルダが新規に作 成され,そこがプロジェクト用フォルダとして利用可能になっているわけです。 5

6.

Chapter 2 データの読み込み・基本操作 図 2.4: Project の作成方法を決める 図 2.5: とりあえず New Project を選ぶ “Existing Directory” を選んだ場合 こちらの場合は,どのフォルダをプロジェクト用フォルダにするかを指定するだけです。図 2.7 のように指定した場合には,C:/Users/Kyosuke Bunji/Desktop/stat_Thu2 というフォルダ がプロジェクト用フォルダになるわけです。 プロジェクトの作成が完了すると,フォルダ内に(プロジェクト名).Rproj というファイル が作成されているはずです。今後データなどは,この .Rproj と同じところに入れていくように しておけば OK です。また,Rstudio を開く場合には .Rproj ファイルをダブルクリックなど して開くようにしてください。 6

7.

2.1 データの読み込み 7 図 2.6: プロジェクトフォルダの作成場所を指定 図 2.7: プロジェクトフォルダの作成場所を指定 2.1 データの読み込み 紙で実施した場合でも Web で実施した場合でも,収集したデータは R で読み込めるように準 備してあげる必要があります。データの形式は,基本的には CSV (Comma Separated Values)*3 にしておけば問題ありません。Excel で入力を行い,保存するときにファイル形式を.csv に指定 *3 CSV は実は普通のテキストファイルです。ただし「各行が一つのレコードを表しており,カンマによって各項 目が区別される」という表記法に従って書かれることによって,ただのテキストでありながらエクセルで表示さ れるようなきれいなデータの構造を保持したものとして扱うものとして作られています。なので CSV ファイル は普通にメモ帳(Mac ならテキストエディット)などでも開けるし,Excel でも開くことができます。

8.

2.1 データの読み込み 8 しておきましょう。もちろん CSV 以外の形式 (.xlsx や.txt など) でも読み込みは可能です。で すが一般的に,1 行 1 レコードで各列が一つの変数を表すマトリクス形式のデータの場合,CSV がデファクトスタンダードな気がします。 本講義では,事前に用意した data.csv というファイルを使用するので,早速これを読み込み ましょう。 データの読み込み (CSV) 1 dat <- read.csv("data.csv") LIGHTBULB 補足:xlsx ファイルの読み込み xlsx ファイルを読み込むための関数は,デフォルトでは用意されていません。よく使われ るのは,readxl パッケージにある read_xlsx() という関数です。ちなみに Rstudio なら ば左上の File → Import Dataset → From Excel…からでも読み込みが可能です。という か read_xlsx() 関数が使えます。 (ただ,エクセルファイルの場合にはセル内改行やセル結合などがあって厄介なことが多い ので気をつけてください…) このように,結構いろいろなファイル形式のもの(SPSS とか STATA とか SAS とかも) を読み込むための関数が様々なパッケージで用意されているので,そういったファイル形 式のデータを読み込みたい場合には,まずは検索してみてください。 データの紹介 今回使用するデータは,psych パッケージの中にあるサンプルデータ bfi をちょっと加工し たものです。ということでここで bfi データの説明をしておきます。 このデータは,オンラインで行われている大規模調査 SAPA (Synthetic Aperture Personality Assessment) Project のデータの一部です。このプロジェクトでは世の中にある大量のパーソナ リティ測定のための項目を集めて,大規模な項目セット (International Personality Item Pool) を作成したりしています。使用している尺度および項目の理論的背景には,心理学では有名な ビッグファイブ Goldberg(1993)というものがあります。すごくざっくり説明すると「人間の 性格特性は 5 つの次元に分類できる・5 つの次元で説明できる」というものです。5 つの次元は, 文献によってちょこちょこ名前が変わったりするのですが,基本的には表 2.1 のものになります (説明は Wikipedia より) 。 表 2.1: ビッグファイブの各次元 次元 協調性 (Agreeableness) 説明 社会的調和に対する一般的関心における個人差を反映する。 協調性がある人物は,他人とうまくやっていくことを大切 にする。

9.

2.2 データフレームの基本操作 次元 9 説明 誠実性 (Conscientiousness) 組織化され信頼できる傾向,自己コントロール能力を示す 傾向,忠実に行動する傾向,達成を目指す傾向,自発的な行 外向性 (Extraversion) 動よりも計画的な行動を好む傾向を表している。 活力,興奮,自己主張,社交性,他人との付き合いで刺激を 神経症傾向 (Neuroticism) 求める,おしゃべりであることを表している。 怒り,不安,抑うつなどの否定的な感情を経験する傾向のこ 開放性 (Openness) とである。 芸術,感情,冒険,珍しいアイディア,想像力,好奇心,お よび多様な経験に対する一般的な評価である。 ということで,データの中には 表 2.2 に示す変数が含まれています。 表 2.2: data.csv の変数 変数名 ID Q1_1 から Q1_25 gender education age 説明 整理番号(元データには無いですが追加しました) 心理尺度の項目(全 25 項目) 性別(1=男性, 2=女性) 最終学歴(1=高校中退,2=高卒,3=大学中退,4=大卒,5=大学院卒) 年齢 心理尺度の項目は,前から順にそれぞれ 5 項目ずつ,協調性,誠実性,外向性,神経症傾向,開 放性を表す項目になっています(具体的な項目は ?psych::bfi でヘルプを参照) 。ビッグファイ ブの細かい理論的なことはともかく,今後の分析の上では「5 項目 ×5 因子の心理尺度」と「性 別・最終学歴・年齢」という変数があるということだけ理解しておいてください。そして,この データだけを使って無理やり全ての分析を紹介するので,結果の解釈などに多少の無理があるこ とはご了承下さい…。 2.2 データフレームの基本操作 データを読み込んだら,まずは正しく読み込めているかをざっと確認します。確認の方法は R ユーザーの数だけ存在すると思いますが,head(),str(),summary(),View() なんかが良く 使われるベーシックな関数ではないか,と思います。ここからは,これらの関数を使ってデータ を確認しながら,おかしな点を確認・修正していきましょう。 head: 最初の数行を表示 1 2 # 変数の数が多いと見にくいのであまり使えない head(dat) 1 2 3 4 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 1 1 2 4 3 4 4 2 3 3 4 4 2 2 2 4 5 2 5 5 4 4 3 4 3 3 5 4 5 4 4 4 5 4 2 5

10.

2.2 データフレームの基本操作 5 6 7 8 9 10 11 12 13 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 3 3 3 4 4 3 4 2 2 1 1 6 4 3 3 3 3 5 2 4 4 4 5 4 5 4 2 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 1 3 3 6 3 4 3 1 -99 16 2 5 4 2 4 3 3 2 -99 18 3 3 4 2 5 5 2 2 -99 17 [ reached 'max' / getOption("max.print") -- omitted 3 rows ] 1 2 3 head() は「とりあえず読み込めているか」の確認程度には使えます。また,データの前処理・ 加工の過程でも,ちょくちょく head() をすることで「今のところうまく行っているか」を確認 したりにも使います。データが読み込めたら,列の名前や入力されている値が想定通りになって いるかを確認しましょう。 幸い(?)なことに,この段階でおかしな値が見つかりました。education は表 2.2 によれば 1 から 5 までの整数しか取らないはずですが,-99 という値が入っています。実は,このデータ では欠測値を -99 に置き換えています。一部のソフトウェアでは,このように欠測値に「絶対あ り得ない数値」を入れておくという処理をする必要があります。ですが R には欠測値を表すた めの NA という特殊な値が用意されているので,-99 を NA に置き換えてあげると良いでしょう。 read.csv() は,デフォルトでは大文字の NA という表記あるいは空白のみを欠測値として認識 しています*4 。こういった場合には,read.csv() の際に引数によって「 -99 は欠測値を表して いるんだよ」ということを伝えた上で再度読み込みましょう。 データの読み込み (欠測値をわからせる) 1 dat <- read.csv("data.csv", na.strings = "-99") このように,ほとんどの関数では,適切に引数を設定してあげることで色々と挙動を変 えることが出来ます。read.csv() 関数で言えば,「文字化けしたとき ( encoding あるいは FileEncoding)」や「1 行目が変数名ではなくいきなりデータが入っているとき ( header)」に も,引数を変えてあげれば対応可能です。 LIGHTBULB ファイルのエンコーディング 文字コードおよび文字化けの仕組みについてはこのページなんかが詳しいと思います(最 終確認日:2024/10/07) 。 文字化けが起こるのは,ファイル作成時の文字コードと読み込み時の文字コードが異な る場合です。現在,日本のパソコンの OS で使用されている文字コードはたいてい”Shift- JIS(CP932)“(主に Windows) か,”UTF-8”(その他)のいずれかでしょう。したがって, *4 自分でデータを入力する際には,欠測値を空白のままにしておくことはおすすめしません。後で見返したときに 転記忘れなのかがわからなくなるためです。面倒でも,明示的に NA と入れておきましょう。 10

11.

2.2 データフレームの基本操作 Windows で作成したファイルを Mac の R で読み込むような場合に,文字化けが発生しや すいです。 そのため,read.csv() する際に「このファイルは Shift-JIS で作られたものだよ」といっ たことを指定してあげることで文字化けを防ぐことができるわけです。よくわからない場 合には,引数 FileEncoding および encoding に以下のいずれかを指定して色々試して みてください。どれか当たると思います。 • shift-jis • CP932 • UTF-8 • UTF-8-BOM 以上の全てでうまく読み込めない場合,そもそも日本語ではないかファイルが破損してい るかのどちらかだと思います…多分…。 ということで,これで -99 だったところがきちんと NA に置き換わったので,引き続きデータ の確認に戻りましょう。 最初の数行を表示 1 2 3 1 2 3 4 5 6 7 8 9 # 第2引数を変えると「最初の何行を表示するか」が変えられる head(dat, 2) # 2行だけ表示 # education列がNAに置き換わっている ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 1 2 4 3 4 4 2 3 3 4 4 2 2 4 5 2 5 5 4 4 3 4 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 1 3 3 3 4 4 3 4 2 2 2 1 1 6 4 3 3 3 3 5 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 1 3 3 6 3 4 3 1 NA 16 2 5 4 2 4 3 3 2 NA 18 1 2 2.2.1 変数の型 学部の統計学の講義では,最初に変数のタイプのお話をすることが多いです。みなさんが受け てきた講義がどうだったかは分かりませんが,私の講義ではそのようにしています。変数のタイ プとは,例えば「量的変数と質的変数」だとか「連続変数と離散変数」 「間隔尺度と順序尺度」な どといった言い方で分類されるものです。統計学において変数のタイプ分けがなぜ重要だった かというと,タイプごとにできる計算・分析が異なるためでした。dat の中身で言えば,最初の 行の ID は見た目は数字ですが,個人を識別するための名義尺度(=質的変数)なので,例えば 11

12.

2.2 データフレームの基本操作 12 「 ID の平均値」を計算しても何の意味もありません。重要なのは,変数のタイプは見た目では判 断できないということです。ID はその後ろの回答データ Q1_1 以降とは明らかに違う型なのです が,特に最初の数行を見ただけでは区別はできません。そこで,R 言語でこうしたデータを扱う 場合には,データの中身(具体的な値)と変数の型をセットにして管理していくことになります。 R 言語では,結構いろいろなタイプのデータ・変数を扱うための「型」が用意されています。 とりあえずデータ分析の範囲で登場する代表的な型としては以下のようなものがあります。 表 2.3: R 言語における代表的な変数の型 型名 integer numeric character factor ordered logical 説明 整数 実数(整数+小数) 文字列 順序なし因子(名義変数などで使用する) 順序つき因子(リッカート尺度にも使う) TRUEと FALSEだけ 例えば同じ「3」という表記でも,integer 型の 3 は四則演算に使える一方,character 型の "3"に別の数字を足し合わせることは出来ません。また,この後出てくる分析の方法のいくつか では,この型の違いによって処理結果が変わることがあります。なので変数の型については多少 知っておくことで,思った通りの分析結果が出なかったときの原因の一つとして考えられるよう になると思います。 INFO (私見)プログラミング言語における「型」 R に限らずほぼすべてのプログラミング言語では,異なる変数のタイプを表すための「型」 という概念が用意されています。それぞれの言語がどのような型を用意しているかは,そ の言語が何を目的として作られたかによって変わってきます。R 言語は,特に統計解析に 特化した言語なので,他の言語ではほぼ見られない factor 型や ordered 型といった「変 数の実質的な意味」による分類の型が用意されています。 統計解析をしない言語であっても「型」の概念は存在しているわけですが,その理由の多 くは「安全性」と「効率」だと思っています。プログラミング言語が使われる場面では, 「絶対にエラーを吐いて停止してはいけない」とか「できるだけ大量のデータを高速でさば きたい」といったことが求められがちです。そこで「想定していない型の変数が来たらそ もそも処理を行わない」とか「変数の型によって異なる処理を用意する」としておくこと で,思わぬエラー(例えば文字列の足し算をしようとしてしまう)を防ぐことができます。 また,変数の型を明示しておくことでメモリの節約や処理速度の向上も見込まれます。例 えば R で x <- 3 という感じで変数を定義する場合,特にその変数の型を指定していま せんが,中身( 3)から,integer 型だろうと推察してくれます。実は integer 型はど こまでも大きな値を取れるわけではなく,-2147483647 から 2147483647 までの整数し かいれることができません。これは,32 ビットの2進数で表せる値の限界です。2進数 で”1111111111111111111111111111111”(1 が 31 個)と表される数が 2147483647 なので す。つまり,R で x <- 3 という指示を出した場合,変数 x の値を保存するために,2進数

13.

2.2 データフレームの基本操作 13 では 0000000000000000000000000000011 として記録することで,仮に 2147483647 が 入っても問題ないようにしています。なんだかもったいないですよね。一個だけなら良い のですが,dat は 2800 人分のデータなので,一つの integer 型の変数ごとに 2800 × 31 個のビット(01)が使われているわけです。これは,もっと大規模なデータを処理する必 要のある環境では結構な問題になってしまいます。例えば dat の中の Q1_1 は 1 から 6 し か取らないとわかっているので,2 進数で表記するためにはビットが 3 つ(001, 010, 011, 100, 101, 110)あれば十分です。 ということでプログラミング言語によっては,このような場合に備えて異なる長さの integer 型が用意されていたりします。確保するメモリを必要最小限にすることで,より 多くのデータを処理できたり,処理速度の向上が見込めるわけです。そしてそこまで厳密 な言語では,変数を宣言する際に例えば int x = 3; という感じで,最初に変数の型を明 示的に指定しておくことが求められます(静的型付け言語) 。そしてその後に異なる型の値 (上の例で言えば小数や文字列など)が入れないよう型にロックをかけてしまいます。これ に対して R 言語では実際に入力された値に応じて勝手に変数の型を予測し,また異なる型 の値が入る際には柔軟に型を変えてくれます(動的型付け言語) 。 動的型付け言語のほうがいちいち変数の型を意識しなくても「いい感じに」処理をしてく れるというメリットがありますが,一方でいつの間にか想定と違う型になっていたりして 処理に失敗するようなケースも出てきてしまいます。R 言語を利用する際は,変数の型に 結構注意する必要がありそうです。 では,実際に dat の中の各変数の型がどのように設定されているかを見てみましょう。自分で 設定した覚えが無くても,R 言語の中で扱う以上は必ずなんらかの型が勝手に設定されているの です。 [str] 各変数の型およびサイズを確認 1 str(dat) 1 2 3 4 5 6 7 8 9 10 11 12 13 'data.frame': 2800 obs. of 29 variables: $ ID : int 1 2 3 4 5 6 7 8 9 10 ... $ Q1_1 : int 2 2 5 4 2 6 2 4 4 2 ... $ Q1_2 : int 4 4 4 4 3 6 5 3 3 5 ... $ Q1_3 : int 3 5 5 6 3 5 5 1 6 6 ... $ Q1_4 : int 4 2 4 5 4 6 3 5 3 6 ... $ Q1_5 : int 4 5 4 5 5 5 5 1 3 5 ... $ Q1_6 : int 2 5 4 4 4 6 5 3 6 6 ... $ Q1_7 : int 3 4 5 4 4 6 4 2 6 5 ... $ Q1_8 : int 3 4 4 3 5 6 4 4 3 6 ... $ Q1_9 : int 4 3 2 5 3 1 2 2 4 2 ... $ Q1_10 : int 4 4 5 5 2 3 3 4 5 1 ... $ Q1_11 : int 3 1 2 5 2 2 4 3 5 2 ... ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​

14.

2.2 データフレームの基本操作 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ Q1_12 : chr $ Q1_13 : int $ Q1_14 : int $ Q1_15 : int $ Q1_16 : int $ Q1_17 : int $ Q1_18 : int $ Q1_19 : int $ Q1_20 : int $ Q1_21 : int $ Q1_22 : int $ Q1_23 : int $ Q1_24 : int $ Q1_25 : int $ gender : int $ education: int $ age : num ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ "3" "1" "4" "3" ... 3 6 4 4 5 6 4 4 NA 4 ... 4 4 4 4 4 5 5 2 4 5 ... 4 3 5 4 5 6 5 1 3 5 ... 3 3 4 2 2 3 1 6 5 5 ... 4 3 5 5 3 5 2 3 5 5 ... 2 3 4 2 4 2 2 2 2 5 ... 2 5 2 4 4 2 1 6 3 2 ... 3 5 3 1 3 3 1 4 3 4 ... 3 4 4 3 3 4 5 3 6 5 ... 6 2 2 3 3 3 2 2 6 1 ... 3 4 5 4 4 5 5 4 6 5 ... 4 3 5 3 3 6 6 5 6 5 ... 3 3 2 5 3 1 1 3 1 2 ... 1 2 2 2 1 2 1 1 1 2 ... NA NA NA NA NA 3 NA 2 1 NA ... 16 18 17 17 17 21 18 19 19 17 ... ​ ​ 14 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ read.csv() 関数を始めとするデータ読み込み系の関数では,各変数(列)の型を,その中 身から推測して自動的に決定してくれます。この時,以下のような規則に従って型が決定され ます。基本的には,型に合わない値(e.g., integer 型なのに文字列が入っている)があるとエ ラーを起こしかねないので「読み込んだデータの中にある全ての値を取りうる型」に決定されま す。つまり, • 整数しかなければ integer 型と考えるのが妥当 • 小数があるけれども全て実数ではある場合,integer 型だと困るので numeric 型とみ なす*5 。 • 文字列がある場合,numeric 型でも困るので character 型とみなす。 ということです。character 型は単なる文字列なので,基本的にはあらゆる表記が許され ます。 変数名の左の int は「この変数が int 型である」ということを意味しています。int とは integer 型のことです。R の処理の上では,整数か小数かはあまり重要ではありませんが,転記 ミスを検出する上では役に立つでしょう。今回のデータの場合,一番下の age は年齢を表す変数 なので整数しか入力されていないはずですが,int ではなく num (numeric 型) と表示されてい ます。つまり,どうやら変数 age には小数が入っている,ということらしいので,後で探して修 正しましょう。また,Q1_12 は chr (character 型) になっています。ということは,Q1_12 のど こかに数字でもない何かが入っている,ということです。これも age と合わせて修正します。 ちなみに,もしもデータが自分で集めたものであれば,修正は R 上よりもローデータをいじっ たほうが早いと思います。ただどこかから拾ってきたデータを使用する場合は,面倒でも R 上 *5 この場合 character 型とみなしても良さそうなものですが,全て実数なので numeric 型とみなしたほうが しっくり来るだろう,と勝手に判断しているということです。

15.

2.2 データフレームの基本操作 15 で処理するようにして,その記録をコードとして残しておくべきと考えます。 2.2.2 データフレーム要素の抽出 read.csv() 関数で読み込んだデータは,R の中ではデータフレームという型*6 のオブジェ クトとして扱われます。読み込んだ時点でそうなっているので普段は気にすることも無いのです が,中身をいじるときには多少その仕組みを知っておいたほうが良いと思います。 データフレームは,表向きには 1 行 1 レコードで各列がそれぞれ異なる変数を表す,いわゆる 普通の(2 次元)データの形式をとっています。ですが内部的には「列の集合」として扱われて います。つまり,今回使用するデータで言えば,図 2.8 のように複数の列があり,これらをまと めたものを「データフレーム」と呼んでいるわけです。このおかげで,列ごとに異なる変数型を とっても良い( numeric と character の混在)わけです。一方同じ 2 次元データでも,行列の 型 ( matrix) の場合,線形代数などの演算を行うために,全ての値は同じ型でなければならない といった決まりがあります。 図 2.8: データフレームの中身 データフレームの要素(中身)を取り出す時には,[ ] という記号を使用します。第 1 章では ベクトルの要素を取り出す方法として同じ記号を紹介しましたが,全く同じことです。データフ レームは表向きには 2 次元データ(行列と同じ)なので,例えば「 i 行 j 列目の要素を取り出し たい」というときには dat[i,j] としてあげましょう。つまり [ ] の中に行番号と列番号をそ れぞれ入れてあげれば良いわけです。行番号と列番号は複数個入れても良いので,ベクトルのと きと同じように,以下のようなことも可能です。 要素指定の方法 (1) 直接数字を入れる 1 2 # 最初の5人の2-6列目=協調性に関する5項目の回答(Q1_1-Q1_5)を見る dat[1:5, 2:6] *6 変数の性質を表すために「型」という概念があるように,データの構造を表すのもまた「型」なのです。

16.

2.2 データフレームの基本操作 1 2 3 4 5 6 1 2 3 4 5 Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 2 4 3 4 4 2 4 5 2 5 5 4 5 4 4 4 4 6 5 5 2 3 3 4 5 要素指定の方法 (2) ベクトルで指定する 1 2 3 4 # 事前に何らかの基準で抽出する人を決めておき,その番号をベクトルに格納する target <- c(258, 392, 1098, 1556, 2003) # それを行番号に入れてあげる dat[target, 25] 1 [1] 6 5 6 6 4 ちなみに,行番号または列番号のいずれか一方だけを指定した場合には,指定されなかったほ うは全て抽出されます。 要素指定の方法 (3) 行番号のみを指定 1 2 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 最初の5人の全回答(すべての列)を見る dat[1:5, ] # つまりhead(dat, 5)と同じ結果 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 1 2 4 3 4 4 2 3 3 4 4 2 2 4 5 2 5 5 4 4 3 4 3 5 4 5 4 4 4 5 4 2 5 4 4 4 6 5 5 4 4 3 5 5 5 2 3 3 4 5 4 4 5 3 2 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 1 3 3 3 4 4 3 4 2 2 2 1 1 6 4 3 3 3 3 5 3 2 4 4 4 5 4 5 4 2 4 5 3 4 4 4 2 5 2 4 5 2 2 5 4 5 2 3 4 4 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 1 3 3 6 3 4 3 1 NA 16 2 5 4 2 4 3 3 2 NA 18 3 3 4 2 5 5 2 2 NA 17 4 1 3 3 4 3 5 2 NA 17 5 3 3 3 4 3 3 1 NA 17 1 2 3 4 5 16

17.

2.2 データフレームの基本操作 要素指定の方法 (4) 列番号のみを指定 1 2 # 全員分の性別(27列目)だけを見る dat[, 27] 1 2 3 4 5 [1] 1 2 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 2 2 1 2 1 2 1 2 2 [28] 2 2 2 2 2 1 2 1 1 1 1 1 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 [55] 1 1 2 1 2 1 1 1 2 2 2 2 1 1 2 2 2 2 1 2 2 2 2 2 2 1 1 [82] 2 1 1 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 [ reached getOption("max.print") -- omitted 2700 entries ] 結果の出力の形が今までとぜんぜん違うように見えますが,これは長いベクトルを表していま す。一番左の [28] は「その行が 28 番目の要素から始まっているよ」という意味なので,例えば 60 番目の人の値を見たければ,[55] から始まる行の左から 6 番目を見ればよいわけです。 Exclamation-Triangle データフレーム要素指定時のカンマ ちなみに,ベクトルと同じようにカンマを使わずに要素を指定したらどうなるでしょうか。 つまり先程の最後のコードを dat[,27] ではなく dat[27] としたら? 指定時にカンマがなくなったら 1 dat[27] 17

18.

2.2 データフレームの基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 gender 1 2 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 2 2 データフレームの場合,カンマがなければ要素番号はそのまま列番号を指定したものとみ なされます。これは図 2.8 に示したように,データフレームが「列の集合」だからです。 あるいは「列のベクトル」という言い方でも良いかもしれません。つまり dat[27] は dat の中にある「27 番目のベクトル」を指示しているわけです。ただ,matrix 型ではこのよ うには機能しないため,混乱を避けるためにも,常に明示的にカンマを入れておくことを おすすめします。 さて,ここまで行番号および列番号を用いてデータフレームの要素を抽出してきました。です が,このように番号で指定するのはあまり良い方法ではないという意見もあります。それは,た とえば後からデータが追加された場合に古いコードが思わぬ挙動をしたり,後からコードを見た ときに「なぜ 27 列目を指定したのか?」といった情報がなくなってしまうためです。というこ とで,可能な限り列の指定に関しては列名を用いて行うことをおすすめします。 要素指定の方法 (5) 変数の名前で指定する 1 2 # 性別(27列目)を見る dat[, "gender"] 1 2 [1] 1 2 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 2 2 1 2 1 2 1 2 2 [28] 2 2 2 2 2 1 2 1 1 1 1 1 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 18

19.

2.2 データフレームの基本操作 3 4 5 19 [55] 1 1 2 1 2 1 1 1 2 2 2 2 1 1 2 2 2 2 1 2 2 2 2 2 2 1 1 [82] 2 1 1 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 [ reached getOption("max.print") -- omitted 2700 entries ] 要素指定の方法 (5-2) 変数の名前で指定する 1 2 1 2 3 4 5 # データフレームの場合,$を使った指定も可能(ただし一つだけ) ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ dat$gender ​ ​ [1] 1 2 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 2 2 1 2 1 2 1 2 2 [28] 2 2 2 2 2 1 2 1 1 1 1 1 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 [55] 1 1 2 1 2 1 1 1 2 2 2 2 1 1 2 2 2 2 1 2 2 2 2 2 2 1 1 [82] 2 1 1 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 [ reached getOption("max.print") -- omitted 2700 entries ] 要素指定の方法 (6) 複数の変数をベクトルで指定する 1 2 3 # デモグラフィック3項目を見るため,ベクトルに列名を格納 varname <- c("gender", "education", "age") dat[, varname] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 gender education age 1 1 NA 16 2 2 NA 18 3 2 NA 17 4 2 NA 17 5 1 NA 17 6 2 3 21 7 1 NA 18 8 1 2 19 9 1 1 19 10 2 NA 17 11 1 1 21 12 1 NA 16 13 2 NA 16 14 1 NA 16 15 1 1 17 16 1 NA 17 17 2 NA 17 [ reached 'max' / getOption("max.print") -- omitted 2783 rows ]

20.

2.2 データフレームの基本操作 LIGHTBULB 細かい話:指定方法の違いと出力の違い データフレームの場合,列の指定の方法がいくつかあります。上の例では,カンマを省略 した場合だけ縦に表示されました。通常,データフレームや行列から 1 行または 1 列だけ を取り出すと,取り出された要素は 1 次元になるため,ベクトルとして扱われる(出力が 横に並ぶ)ようになります。なのですが,カンマを省略した場合だけは「1 列のデータフ レーム」として扱われるという挙動になっています。もしも今後みなさんが使用する関数 で「データフレーム型しか受け付けない,ベクトルはダメ」という関数があった場合は, データフレーム型のままにしておく必要があるかもしれません。 ただ,「カンマを省略すると 1 列のデータフレームになる」と言うのはあくまでもデー タフレーム型特有の挙動なので,こんな細かいことをいちいち覚えているのはあまり効 率的ではありません。そこで(かなりマニアックな)別の方法をお教えします。それは drop=FALSE という引数を使う方法です。 1 行または 1 列だけを取り出したときにベクトルに型変換される,というのは,複数行・列 が無いためにデータフレームの型を保てず,結果的にベクトル型に落ちた,という見方が 出来ます。その「落ちた」をおさえるのが drop=FALSE です。 drop=FALSE の使い方 1 dat[, "gender", drop = FALSE] 1 2 3 4 5 6 7 8 9 10 11 12 gender 1 1 2 2 3 2 4 2 5 1 6 2 7 1 8 1 9 1 10 2 [ reached 'max' / getOption("max.print") -- omitted 2790 rows ] 使用する際には,上記のように,列番号の後に drop=FALSE を指定してあげると,カンマ を省略した dat["gender"] と同じ結果が得られます。 列を指定する際は番号ではなく列名で行う,という話をしましたが,行のほうはどうしましょ うか。行には名前はありません。行にも列にも(ベクトルでも)使える別の指定方法が logical 型で指定するという方法です。数字や名前の代わりに行数・列数と同じ長さの logical 型ベク トルを指定した場合,TRUE のところだけが抽出される仕組みになっています。まずは簡単なベ クトルでその挙動を確認しましょう。 20

21.

2.2 データフレームの基本操作 ベクトルの要素を TRUE/FALSE で指定 1 2 vec <- 6:10 # c(6,7,8,9,10)と同じ vec[c(TRUE, FALSE, TRUE, FALSE, TRUE)] # 1,3,5番目がTRUE 1 [1] 6 8 10 これを利用して,データフレームの最初の 3 行を logical 型を使って取り出してみます。 logical 型で指定 1 2 3 4 5 6 7 # 長さ2800のベクトルを作成 # 最初の3つがTRUE,後はFALSE # rep()は同じものを並べたベクトルを作る関数 vec <- c(rep(TRUE, 3), rep(FALSE, 2797)) 1 2 3 4 5 6 7 8 9 10 11 12 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 1 1 2 4 3 4 4 2 3 3 4 4 2 2 2 4 5 2 5 5 4 4 3 4 3 3 5 4 5 4 4 4 5 4 2 5 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 1 3 3 3 4 4 3 4 2 2 2 1 1 6 4 3 3 3 3 5 3 2 4 4 4 5 4 5 4 2 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 1 3 3 6 3 4 3 1 NA 16 2 5 4 2 4 3 3 2 NA 18 3 3 4 2 5 5 2 2 NA 17 # このベクトルを行の指定に使う dat[vec, ] LIGHTBULB 細かい話:logical 型の長さが足りないとどうなる? ​ ​ これは実際にやってみると分かるのですが,例えば dat[TRUE,] とした場合には,全ての 行が抽出されます。続いて dat[c(TRUE,FALSE),] とした場合には,奇数番目の行だけが 抽出されます。 R で は, 長 さ が 足 り な い と き に は リ サ イ ク ル す る (繰 り 返 す) と い う ル ー ル が あ り ま す。 し た が っ て, dat[TRUE,] の 場 合 に は 長 さ 2800 に な る ま で TRUE (2800 回) 繰 り 返 さ れ た た め に 全 て の 行 が 表 示 さ れ, dat[c(TRUE,FALSE),] の 場 合 に は 長 さ 2800 に な る ま で c(TRUE,FALSE) が (1400 回) 繰 り 返 さ れ た 結 果 TRUE,FALSE,TRUE,FALSE,TRUE,FALSE,... となったために奇数行だけが取り出され ているのです。 21

22.

2.2 データフレームの基本操作 この挙動をうまく使えば,「奇数番目だけ取り出す」や「4 の倍数の列だけ取り出す」と いったアクションも可能となりますが,実質的にこれは行/列番号で指定する方法と変わ らない不安定さを持っているので,慣れないうちは手を出さないことをおすすめします。 データフレームの長さと同じ長さの logical 型ベクトルは,比較演算子によって容易に生み 出すことが出来ます。例えば「男性 ( gender が 1 の人) だけを見たい」としたら,まず抽出した い人のところが TRUE になっているベクトルを作ります。 条件に当てはまる人の行を特定する 1 2 vec <- dat[, "gender"] == 1 # genderが1の人のところがTRUEになる vec 1 2 3 4 5 6 7 8 9 10 11 12 13 [1] TRUE FALSE FALSE FALSE TRUE FALSE TRUE TRUE TRUE [10] FALSE TRUE TRUE FALSE TRUE TRUE TRUE FALSE TRUE [19] FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE [28] FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE [37] TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE [46] TRUE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE [55] TRUE TRUE FALSE TRUE FALSE TRUE TRUE TRUE FALSE [64] FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE [73] TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE [82] FALSE TRUE TRUE FALSE TRUE FALSE FALSE FALSE FALSE [91] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE [100] FALSE [ reached getOption("max.print") -- omitted 2700 entries ] あとは以下のように,行指定の場所にベクトルを与えるだけで抽出可能なわけです*7 。 条件に当てはまる人を抽出する 1 1 2 3 4 5 6 7 8 dat[vec, ] ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 1 2 4 3 4 4 2 3 3 4 4 5 2 3 3 4 5 4 4 5 3 2 7 2 5 5 3 5 5 4 4 2 3 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 1 3 3 3 4 4 3 4 2 2 5 2 2 5 4 5 2 3 4 4 7 4 3 4 5 5 1 2 2 1 1 5 7 *7 ちなみにイコールが一つだけ ( =) の場合は <-と同じく代入の働きをします。よくあるミスなのでご注意くだ さい。 22

23.
[beta]
2.2 データフレームの基本操作

9
10
11
12
13

Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age
1
3
3
6
3
4
3
1
NA 16
5
3
3
3
4
3
3
1
NA 17
7
1
5
2
5
6
1
1
NA 18
[ reached 'max' / getOption("max.print") -- omitted 916 rows ]

もちろん 1 行にまとめて
1

dat[dat[, "gender"] == 1, ]

としても OK です。このあたりは見やすい方を選んでください。
他の比較演算子もまとめて紹介します。
比較演算子 (1) 不等号
1
2
3
4

# 年齢が21歳より上(大なり)の人
# 「小なり」の場合不等号を逆に(<)
vec <- dat[, "age"] > 21
dat[vec, ]

1
2
3
4
5
6
7
8
9
10
11
12
13

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
23 23
1
5
6
5
6
4
3
2
4
5
24 24
2
6
5
6
5
3
5
6
3
6
27 27
2
4
4
4
3
6
5
6
1
1
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
23
2
1
2
5
2
2
2
2
2
24
2
2
4
6
6
4
4
4
6
27
2
4
4
2
6
3
3
5
3
Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age
23
2
6
1
5
5
2
1
5 68
24
6
6
1
5
6
1
2
2 27
27
2
5
2
6
6
1
2
5 51
[ reached 'max' / getOption("max.print") -- omitted 1878 rows ]

比較演算子 (2) 大なり・小なりイコール
1
2
3
4
5

# 年齢が21歳以上(大なりイコール)の人
# 「小なりイコール」の場合不等号だけ逆に(<=)
# つまり日本語での読み方と同じ順に記号を書けば良い
vec <- dat[, "age"] >= 21
dat[vec, ]

23

24.
[beta]
2.2 データフレームの基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
6
6
6
6
5
6
5
6
6
6
1
3
11 11
4
4
5
6
5
4
3
5
3
2
23 23
1
5
6
5
6
4
3
2
4
5
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
6
2
1
6
5
6
3
5
2
2
11
1
3
2
5
4
3
3
4
2
23
2
1
2
5
2
2
2
2
2
Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age
6
3
4
3
5
6
1
2
3 21
11
3
5
3
5
6
3
1
1 21
23
2
6
1
5
5
2
1
5 68
[ reached 'max' / getOption("max.print") -- omitted 2022 rows ]

比較演算子 (3) ノットイコール
1
2
3
1
2
3
4
5
6
7
8
9
10
11
12
13

# 年齢が21歳ではない(ノットイコール)人
vec <- dat[, "age"] != 21
dat[vec, ]

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
1
2
4
3
4
4
2
3
3
4
4
2
2
4
5
2
5
5
4
4
3
4
3
5
4
5
4
4
4
5
4
2
5
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
1
3
3
3
4
4
3
4
2
2
2
1
1
6
4
3
3
3
3
5
3
2
4
4
4
5
4
5
4
2
Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age
1
3
3
6
3
4
3
1
NA 16
2
5
4
2
4
3
3
2
NA 18
3
3
4
2
5
5
2
2
NA 17
[ reached 'max' / getOption("max.print") -- omitted 2653 rows ]
1
2
3

ちなみにノットイコールで使用した !記号は,多くの場面で TRUE と FALSE をひっくり返す役
割を持っています。これは結構多用すると思うので覚えておきましょう(後でも出てきます)
。

!で結果をひっくり返す
1
2
3

# 年齢が21歳の(ノットイコールの逆=イコール)人
vec <- !(dat[, "age"] != 21)
dat[vec, ]

24

25.

2.2 データフレームの基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10 6 6 6 6 5 6 5 6 6 6 1 3 11 11 4 4 5 6 5 4 3 5 3 2 38 38 1 4 4 2 3 6 5 6 3 4 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19 6 2 1 6 5 6 3 5 2 2 11 1 3 2 5 4 3 3 4 2 38 3 4 3 3 5 5 6 5 5 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 6 3 4 3 5 6 1 2 3 21 11 3 5 3 5 6 3 1 1 21 38 4 5 5 4 5 2 1 3 21 [ reached 'max' / getOption("max.print") -- omitted 141 rows ] ただし実のところ,logical 型ベクトルで行を指定すると,NA 周りで面倒なことになります。 なので特定の条件を満たす行を抽出する場合には,代わりに subset() 関数を使うようにしてく ださい。 Exclamation-Triangle 行抽出時に NA があるとどうなるのか 百聞は一見にしかずということで,早速やってみましょう。 logical 型ベクトルに NA がある場合 1 2 # 変数educationは,一部の人がNA(無回答)になっている dat[, "education"] == 1 1 2 3 4 5 6 7 8 9 10 11 12 13 [1] NA NA NA NA NA FALSE NA FALSE TRUE [10] NA TRUE NA NA NA TRUE NA NA NA [19] NA NA NA NA FALSE FALSE TRUE FALSE FALSE [28] NA FALSE FALSE NA FALSE FALSE NA FALSE FALSE [37] FALSE FALSE NA FALSE FALSE FALSE TRUE FALSE FALSE [46] FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE [55] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE [64] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE [73] FALSE FALSE FALSE FALSE NA NA FALSE FALSE FALSE [82] FALSE NA FALSE TRUE FALSE FALSE FALSE FALSE FALSE [91] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE [100] FALSE [ reached getOption("max.print") -- omitted 2700 entries ] 例えば dat[,"education"] == 1 という比較演算が行われると,1 の人は TRUE,それ以 外の人は FALSE になりそうなものですが,実際には NA の人は NA が返ってきます。 25

26.
[beta]
2.2 データフレームの基本操作

行指定に NA がある場合
1

dat[dat[, "education"] == 1, ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA.1 NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA.2 NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
NA
NA <NA>
NA
NA
NA
NA
NA
NA
NA
NA.1
NA <NA>
NA
NA
NA
NA
NA
NA
NA
NA.2
NA <NA>
NA
NA
NA
NA
NA
NA
NA
Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education
NA
NA
NA
NA
NA
NA
NA
NA
NA
NA.1
NA
NA
NA
NA
NA
NA
NA
NA
NA.2
NA
NA
NA
NA
NA
NA
NA
NA
age
NA
NA
NA.1 NA
NA.2 NA
[ reached 'max' / getOption("max.print") -- omitted 444 rows ]

このように,logical 型による行指定の際に NA が入っていると,そこには「全ての変数
が NA になった行」が誕生します。酷い話です。具体的にこれが引き起こす問題としては,

• 平均値などを計算しようとしたときに NA が入っているために計算ができない
( na.rm=TRUE としたら良いですが)

• 行の数が「条件に合うデータ( TRUE)の数」と合わないために計算や関数の挙動が
おかしくなる
などが考えられます。

[subset] 条件を満たす行を抽出する
1
2

# 大卒以上だけ
subset(dat, education >= 4)

1
2
3
4
5
6
7

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
23 23
1
5
6
5
6
4
3
2
4
5
27 27
2
4
4
4
3
6
5
6
1
1
33 33
1
5
6
5
4
1
5
6
4
6
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
23
2
1
2
5
2
2
2
2
2
27
2
4
4
2
6
3
3
5
3

26

27.

2.2 データフレームの基本操作 8 9 10 11 12 13 27 33 6 6 2 1 1 1 2 1 3 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education age 23 2 6 1 5 5 2 1 5 68 27 2 5 2 6 6 1 2 5 51 33 6 6 6 5 6 1 1 5 23 [ reached 'max' / getOption("max.print") -- omitted 809 rows ] これでようやく,エラーの確認と修正をする準備が整いました。先程見つかったエラーは,age と Q1_12 の中に,それぞれ integer 型ではない値が入っている,ということでした。まずは エラーの箇所を特定しましょう。やり方は色々ありますが,ここでは table() を使った方法で やってみます。table() 関数は,変数の度数分布表を作成してくれる関数です。はじめに度数分 布表を作成し,おかしな値があれば直接指定してあげる,という方法で確認してみます。 [table] 度数分布表を作る 1 table(dat[, "Q1_12"]) 1 2 3 1 2 3 4 5 6 532 670 343 599 385 254 l 1 おかしなデータの人を見つける 1 2 # 一人だけイチじゃなくてエルのひとがいるようだ subset(dat, Q1_12 == "l") 1 2 3 4 5 6 7 8 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 1449 1449 1 5 5 6 6 6 6 6 1 Q1_10 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 1449 1 1 l 2 6 6 1 2 2 Q1_19 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender 1449 2 1 6 1 6 5 2 2 education age 1449 5 27 そして,元の質問紙を見て,ここにはたしかに数字のイチ ( 1) が入っているようであれば,直 接代入してあげます*8 。元データに当たる事ができない場合には,仕方ないですが欠測値 NA に 置き換えましょう。 *8 さすがに手書きじゃないんだから実際にイチ ( 1) とエル ( l) を間違えることは無いと思いますが,R のコード をコピペしたりすると,実際にたまにこういうミスが混入していたりします。

28.
[beta]
2.2 データフレームの基本操作
おかしなデータを直接見つけて修正
1

dat[dat[, "ID"] == 1449, "Q1_12"] <- 1

上記のコードは,dat[1449, "Q1_12"] <- 1 としても良さそうなものですが,あえて回りく
どい書き方をしています。それは行が変わっても意図した修正が行われるようにするためです。
例えばこの前か後ろで「ID: 1 の人を除外する」処理を追加したとします。すると,最初の行が
まるまる消えてしまうので,ID:1449 さんは dat の中の 1448 行目に来てしまいます。そのとき
に dat[1449, "Q1_12"] <- 1 を実行すると,ID:1449 さんの代わりに一つ下にいた ID:1450
さんの Q1_12 が 1 に置き換わってしまいます。そういったトラブルを避けるために,きちんと
「ID:1449 さんの Q1_12 を変更してね」と指示を明確にしているわけです。
ということでエルをイチに修正することはできましたが,まだこの段階では変数 Q1_12 の型
が character 型のままなので,最後にこの変数を型変換してあげます。型変換のための関数
は as.***() という名前です。integer 型にしたい場合は as.integer() としてあげれば OK
です。
変数の型の変換
1

dat[, "Q1_12"] <- as.integer(dat[, "Q1_12"])

同じように age についてもやってみます。ただ,age は年齢なので,取りうる値が多岐にわ
たります。まだ年齢なら良いですが,連続変数だと手の施しようがありません。さてどうしよう
か…このやり方はいくつか考えられると思います。最終的にエラーの箇所を特定さえできればよ
いのですが,今回は次のような方法で特定を試みることにします。
変数 age は numeric 型なので,小数が入っている人がいるのは確かです。つまり小数部分
がゼロではない人がエラーである,ということが言えます。ここで使用するのは floor() とい
う関数です。これは,与えられた数の小数点以下を切り捨てるものです*9 。つまり,age から

floor(age) を引いた値は小数点以下を表しているということです。
整数ではないデータを見つける一つの方法
1
2

# ageの小数部分がゼロではない人をsubset
subset(dat, age - floor(age) != 0)

1
2
3
4
5
6
7

ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 Q1_10
793 793
1
5
1
5
6
3
5
5
4
1
Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 Q1_19
793
1
4
4
5
5
2
5
1
1
Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender education
793
1
6
1
6
6
5
2
1
age
*9 お友達には,切り上げを行う ceiling() や,四捨五入的なことを行う round() があります。

28

29.

2.3 要約統計量の確認 8 29 793 3.7 見つけたら修正 1 2 3 4 5 # ローデータを見たとして,37歳に修正 dat[dat[, "ID"] == 793, "age"] <- 37 # integer型に修正 # numeric型からinteger型には直さなくても別に問題はない dat[, "age"] <- as.integer(dat[, "age"]) これでようやくローデータのミスが修正できました。次の確認に移りましょう。 2.3 要約統計量の確認 R にデフォルトで入っている summary() や,psych::describe(),Hmisc::describe() と いった関数は,各変数の要約統計量を出してくれるものです。どれを使っても良い*10 のですが, ここでは summary() を使って変数の確認をしてみます。 INFO 関数名の左にパッケージ名を書いておく psych::describe() など,関数名の左にパッケージ名と :: を書いた表現は,どのパッ ケージの関数を使うかを明示するものです。例えば psych と Hmisc パッケージを両方と も library() した状態で describe() 関数を呼び出そうとすると,基本的には後に読み 込んだほうの describe() 関数が呼び出されるようになっているはずです(ちなみにどの パッケージの関数が呼び出されているかは,help() を使ったりするとわかります) 。 だとすると,もし「 Hmisc パッケージの describe() 関数」を呼び出したい場合には,そ もそも psych パッケージを library() しないようにしたり,両方 library() するにし てもその順番を変える必要がありますが,これは明らかに面倒です。 このような場合に,Hmisc::describe() というように書けば,他のパッケージにある describe() 関数は気にせずに,確実に「 Hmisc パッケージの describe() 関数」を呼び 出せるわけです。 また,この記法による関数の呼び出しは,パッケージを library() していなくても使え ます。そのため,あるパッケージの関数を一度しか使わない場合など「 library() するほ どではない」ときにも使えるので覚えておきましょう。上述したように,同名の関数の思 わぬ衝突を避けられるかもしれません。 *10 psych::describe() を使うと「 NA ではない数」「標準偏差」「トリム平均」「尖度」「歪度」なども出してくれ ますが,第1・3四分位点は出してくれません(引数 quant で追加は可能)。また Hmisc::describe() では データの内容に合わせて度数分布や最大値・最小値トップ5を出してくれたり,いろいろな分位点を出してくれ ます。結局のところ,好きな関数を使えば OK です。

30.

2.3 要約統計量の確認 30 [summary] 量的変数の平均値や最大値・最小値などをチェック 1 2 # 全部表示すると長いので出力は省略しています summary(dat) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ID Min. : 1.0 1st Qu.: 700.8 Median :1400.5 Mean :1400.5 3rd Qu.:2100.2 Max. :2800.0 Q1_3 Min. :1.000 1st Qu.:4.000 Median :5.000 Mean :4.604 3rd Qu.:6.000 Max. :6.000 NA's :26 Q1_6 Min. :1.000 1st Qu.:4.000 Median :5.000 Mean :4.502 3rd Qu.:5.000 Max. :6.000 NA's :21 Q1_1 Q1_2 Min. :1.000 Min. :1.000 1st Qu.:1.000 1st Qu.:4.000 Median :2.000 Median :5.000 Mean :2.413 Mean :4.802 3rd Qu.:3.000 3rd Qu.:6.000 Max. :6.000 Max. :6.000 NA's :16 NA's :27 Q1_4 Q1_5 Min. :1.0 Min. : 1.000 1st Qu.:4.0 1st Qu.: 4.000 Median :5.0 Median : 5.000 Mean :4.7 Mean : 4.582 3rd Qu.:6.0 3rd Qu.: 6.000 Max. :6.0 Max. :44.000 NA's :19 NA's :16 Q1_7 Q1_8 Min. :1.00 Min. :1.000 1st Qu.:4.00 1st Qu.:4.000 Median :5.00 Median :5.000 Mean :4.37 Mean :4.304 3rd Qu.:5.00 3rd Qu.:5.000 Max. :6.00 Max. :6.000 NA's :24 NA's :20 確認したところ,Q1_5 に最大値 44 が見られました。これまでと同じように修正していきま しょう。今回は「最大値が 44 の人がいる」ということまでしか分かっていません。もしかした ら 6 より大きく 44 より小さい人もいるかもしれないので,不等号を使って subset() してあげ ます。 おかしな値を見つける 1 2 # Q1_5が6より大きい人をsubset subset(dat, Q1_5 > 6) 1 2 3 4 5 ID Q1_1 Q1_2 Q1_3 Q1_4 Q1_5 Q1_6 Q1_7 Q1_8 Q1_9 286 286 1 5 5 6 44 5 4 5 2 2235 2235 1 4 4 2 22 4 3 4 4 Q1_10 Q1_11 Q1_12 Q1_13 Q1_14 Q1_15 Q1_16 Q1_17 Q1_18 286 1 1 3 5 6 5 3 4 4

31.

2.4 GUI で細かいチェック 6 7 8 9 10 11 12 31 2235 6 4 5 2 1 2 5 5 Q1_19 Q1_20 Q1_21 Q1_22 Q1_23 Q1_24 Q1_25 gender 286 3 4 5 3 4 4 2 2 2235 5 4 5 3 5 6 2 2 education age 286 3 19 2235 3 19 5 おかしな値を修正する 1 2 3 # それぞれローデータを見たとして,正しい値に修正 dat[dat[, "ID"] == 286, "Q1_5"] <- 4 dat[dat[, "ID"] == 2235, "Q1_5"] <- 2 ちなみに,summary() 系の関数は,変数の型に応じた要約統計量を返してくれます。 型によって異なる要約 (1) logical 型の場合 1 summary(dat[, "gender"] == 1) 1 2 Mode logical FALSE 1881 TRUE 919 型によって異なる要約 (2) character 型の場合 1 1 2 summary(as.character(dat[, "Q1_1"])) Length Class Mode 2800 character character 型によって異なる要約 (2) factor 型の場合 1 summary(as.factor(dat[, "Q1_1"])) 1 2 1 922 2 818 3 402 4 337 5 223 6 NA's 82 16 2.4 GUI で細かいチェック View() は,図 2.9 のように Rstudio の中に操作可能なビューワーを表示してくれる関数で す。値を書き換えることは出来ませんが,特定の列でソートしたり,フィルターをかけたりは出 来ます。生の R でも使えますが,日本語が文字化けしたり,本当にただ表示するだけなので使い 勝手はあまり良くありません。

32.

2.5 データの保存 32 データを操作して眺める 1 2 3 # 気になるところがあれば細かくチェックするために # 正直いうと,csvに書き出してExcelで開いても良いと思います View(dat) 図 2.9: View() のあと Rstudio に表示されるもの 2.5 データの保存 R を開くたびに毎回元データを読み込んでコードを全部回すのは非効率&データサイズが大き いと時間がかかってしまうので,コードファイルは適当なところで区切り,処理後のデータを保 存しておく(セーブポイントを作る)のがおすすめです。この授業では,各回の最後の時点での データオブジェクトを保存しておくことにします。 2.5.1 CSV に保存する CSV に保存する場合は,write.csv() を使います。2 つ目の引数が,保存するファイルの名 前を指しています。他にもいくつかの引数がありますが,適宜設定しましょう。 引数名 na 説明 NA のところにどういう文字を入れておくか。デフォルトは na="NA"です が,他のソフトウェアで分析を続ける場合には変更する必要があるかもし れません。

33.

2.5 データの保存 引数名 row.names 33 説明 一番左の列に,行の名前*11 を入れるかを選びます。デフォルトでは行番号 が入るのですが,これをまた読み込む際に行番号の列が 1 列目になり,全 ての列が一つ右にずれることになります。そのため行の名前に特別な意味 col.names がなければ,FALSE にしておくことをおすすめします。 先頭行に,列の名前を入れるかを選びます。普通は入れておけば良いです が,これもソフトウェアによっては「列名を入れるな。データだけにしろ。 」 というものもあるので,そのような際には FALSE にしてあげてください。 CSV に書き込む 1 write.csv(dat, "chapter02.csv", row.names = FALSE) 2.5.2 オブジェクトのまま保存する CSV で保存することのメリットは,Excel を始めとした別のソフトウェアでも読み込みが可能 という点です。したがって,異なるソフトウェアで分析する際などには CSV が良いでしょう。 一方で,CSV に保存する場合,変数の型( factor 型に変換した変数など)の情報は記録され ないため,読み込むたびに改めて行わなければいけない処理が発生します。また CSV はデータ フレームや行列などの 2 次元配列までしか保存できないため,今後行う分析結果を保存する際に は,CSV は使えません。 このような場合,R オブジェクトのまま保存するという手段があります。この授業でも,データ の保存はこちらの方法で行うことにします。特定のオブジェクトを保存する際には,saveRDS() という関数を使います(読み込みは次回の最初に) 。 R オブジェクトのまま保存する 1 2 3 # 拡張子は大文字でも小文字でも(というかrdsにしなくても)良いですが, # たぶん.rdsが最もメジャーです。 saveRDS(dat, "chapter02.rds") saveRDS() では一つのオブジェクトだけを保存しますが,場合によっては複数のオブジェク トをまとめて保存したい,何なら現時点での状態をそのまままるごと保存しておきたい,という 場合もあるでしょう。そのような場合は save() や save.image() 関数が使えます。 複数オブジェクトを保存 1 2 3 # save()およびsave.image()関数で保存する場合は.rdataとする習わしがあります。 # .rdsと.rdataの違いについては次回… save(dat, vec, file = "chapter02.rdata") *11 ID 列とは別の話です。R ではデータフレームの中で,列とは別の扱いとして「行の名前」が指定できます。列 名が「1 行目」としては扱われないのと同じ感じです。

34.

2.5 データの保存 4 5 34 # ワークスペース全体を保存してくれる save.image(file = "chapter02_all.rdata") ちなみに save.image() でやっていることは,R や Rstudio を閉じようとした際の質問で「保 存」を選んだ時と同じです。この場合にはファイル名は指定できずに必ず(ドットの前に何もな い)".Rdata"という名前になります。が,使う分には問題ありません。 図 2.10: R を閉じる時

35.

参考文献 参考文献 Goldberg, L. R. (1993). The structure of phenotypic personality traits. American Psychologist, 48(1), 26–34. https://doi.org/10.1037/0003-066X.48.1.26 35