データ構造

最終更新日:2024-11-22 | ページの編集

所要時間: 55分

概要

質問

  • R でデータをどのように読み取ることができますか?
  • R の基本的なデータ型は何ですか?
  • R でカテゴリ情報をどのように表現しますか?

目的

  • 5 つの主なデータ型を特定できるようになる。
  • データフレームを探索し始め、ベクトルやリストとの関連を理解する。
  • R からオブジェクトの型、クラス、構造に関する質問ができるようになる。
  • “names”、“class”、“dim” 属性の情報を理解する。

R の最も強力な機能の 1 つは、スプレッドシートや CSV ファイルにすでに保存されているような表形式データを処理する能力です。まずは、data/ ディレクトリに feline-data.csv という名前の小さなデータセットを作成しましょう:

R

cats <- data.frame(coat = c("calico", "black", "tabby"),
                    weight = c(2.1, 5.0, 3.2),
                    likes_catnip = c(1, 0, 1))

次に、cats を CSV ファイルとして保存します。引数名を明示的に指定することは良い習慣であり、関数が変更されたデフォルト値を認識できます。この場合は row.names = FALSE を設定しています。引数名やそのデフォルト値を確認するには、?write.csv を使用してヘルプファイルを表示してください。

R

write.csv(x = cats, file = "data/feline-data.csv", row.names = FALSE)

新しいファイル feline-data.csv の内容は次の通りです:

R

coat,weight,likes_catnip
calico,2.1,1
black,5.0,0
tabby,3.2,1

ヒント: R でテキストファイルを編集する

または、テキストエディタ(Nano)や RStudio の File -> New File -> Text File メニュー項目を使用して data/feline-data.csv を作成することもできます。

このデータを R に読み込むには、以下のコマンドを使用します:

R

cats <- read.csv(file = "data/feline-data.csv")
cats

出力

    coat weight likes_catnip
1 calico    2.1            1
2  black    5.0            0
3  tabby    3.2            1

read.table 関数は、CSV ファイル(csv = comma-separated values)などのテキストファイルに保存された表形式データを読み取るために使用されます。タブやカンマは、CSV ファイルでデータポイントを区切るために最も一般的に使用される記号です。R では read.table の便利なバージョンとして read.csv(データがカンマで区切られている場合)と read.delim(データがタブで区切られている場合)が用意されています。この 3 つの中で、read.csv が最も一般的に使用されます。必要に応じて、デフォルトの区切り記号を変更することもできます。

データが因子かどうかを確認する

最近、R がテキストデータを処理する方法が変更されました。以前は、R はテキストデータを自動的に “因子” という形式に変換していましたが、現在は “文字列” という形式で処理されるようになりました。因子の使用用途については後ほど学びますが、ほとんどの場合は必要なく、使用することで複雑になるだけです。そのため、新しい R バージョンではテキストデータが “文字列” として読み取られます。因子が自動的に作成されているかを確認し、必要に応じて文字列形式に変換してください:

  1. 入力データの型を確認するには、str(cats) を入力します。
  2. 出力で、コロンの後にある 3 文字のコードを確認します:numchr のみが表示される場合は、レッスンを続けることができます。このボックスはスキップしてください。fct が見つかった場合は、次の手順に進んでください。
  3. R が因子データを自動的に作成しないようにするには、以下のコードを実行します:options(stringsAsFactors = FALSE)。その後、cats テーブルを再読み込みして変更を反映させます。
  4. R を再起動するたびに、このオプションを設定する必要があります。忘れないように、データを読み込む前にスクリプトの最初の行のいずれかに含めてください。
  5. R バージョン 4.0.0 以降では、テキストデータは因子に変換されなくなりました。問題を回避するためにこのバージョン以降をインストールすることを検討してください。研究所や会社のコンピュータを使用している場合は、管理者に依頼してください。

データセットをすぐに探索し始めることができます。たとえば、$ 演算子を使用して列を指定します:

R

cats$weight

出力

[1] 2.1 5.0 3.2

R

cats$coat

出力

[1] "calico" "black"  "tabby" 

列に対して操作を実行することもできます:

R

## たとえば、スケールが 2kg 軽いことが判明した場合:
cats$weight + 2

出力

[1] 4.1 7.0 5.2

R

paste("My cat is", cats$coat)

出力

[1] "My cat is calico" "My cat is black"  "My cat is tabby" 

しかし、次のコードではどうでしょうか?

R

cats$weight + cats$coat

エラー

Error in cats$weight + cats$coat: non-numeric argument to binary operator

ここで何が起こったのかを理解することが、R でデータを成功裏に分析する鍵です。

データ型

最後のコマンドがエラーを返す理由が 2.1"black" を加算するのは無意味だからだと推測したなら、あなたは正しいです!これはプログラミングにおける重要な概念である データ型 に関する直感をすでに持っているということです。データの型を調べるには、次のように入力します:

R

typeof(cats$weight)

出力

[1] "double"

主なデータ型は次の 5 種類です:doubleintegercomplexlogicalcharacter。 歴史的な理由で、doublenumeric とも呼ばれます。

R

typeof(3.14)

出力

[1] "double"

R

typeof(1L) # L サフィックスを付けると数値を整数に強制します(R はデフォルトで浮動小数点数を使用)

出力

[1] "integer"

R

typeof(1+1i)

出力

[1] "complex"

R

typeof(TRUE)

出力

[1] "logical"

R

typeof('banana')

出力

[1] "character"

分析がどれだけ複雑であっても、R ではすべてのデータがこれらの基本的なデータ型のいずれかとして解釈されます。この厳格さには非常に重要な意味があります。

別の猫の詳細を追加した情報が、ファイル data/feline-data_v2.csv に保存されています。

R

file.show("data/feline-data_v2.csv")

R

coat,weight,likes_catnip
calico,2.1,1
black,5.0,0
tabby,3.2,1
tabby,2.3 or 2.4,1

この新しい猫データを以前と同じ方法で読み込み、weight 列にどのようなデータ型が含まれているか確認します:

R

cats <- read.csv(file="data/feline-data_v2.csv")
typeof(cats

$weight)

出力

[1] "character"

あらら、weight 列の型が double ではなくなっています!以前と同じ計算を試みると、問題が発生します:

R

cats$weight + 2

エラー

Error in cats$weight + 2: non-numeric argument to binary operator

何が起こったのでしょうか? 私たちが扱っている cats データは データフレーム と呼ばれるものです。データフレームは、R で最も一般的で多用途な データ構造 の 1 つです。 データフレームの特定の列には異なるデータ型を混在させることはできません。 この場合、R はデータフレーム列 weight のすべてを double として読み取らなかったため、列全体のデータ型がその列内のすべてに適した型に変わります。

R が CSV ファイルを読み取ると、それは データフレーム として読み込まれます。そのため、cats CSV ファイルを読み込むと、データフレームとして保存されます。データフレームは str() 関数によって表示される最初の行で認識できます:

R

str(cats)

出力

'data.frame':	4 obs. of  3 variables:
 $ coat        : chr  "calico" "black" "tabby" "tabby"
 $ weight      : chr  "2.1" "5" "3.2" "2.3 or 2.4"
 $ likes_string: int  1 0 1 1

データフレーム は行と列で構成され、各列は同じ数の行を持ちます。データフレームの異なる列は異なるデータ型で構成できます(これがデータフレームを非常に柔軟にする理由です)が、特定の列内ではすべてが同じ型である必要があります(例:ベクトル、因子、リストなど)。

この振る舞いをさらに調査する間、猫のデータから余分な行を削除し、それを再読み込みしましょう:

feline-data.csv:

coat,weight,likes_catnip
calico,2.1,1
black,5.0,0
tabby,3.2,1

そして RStudio 内で:

R

cats <- read.csv(file="data/feline-data.csv")

ベクトルと型の強制変換

この挙動をよりよく理解するために、別のデータ構造である ベクトル を紹介します。

R

my_vector <- vector(length = 3)
my_vector

出力

[1] FALSE FALSE FALSE

R におけるベクトルは、基本的に順序付けられた要素のリストです。ただし、特別な条件として、ベクトル内のすべての要素は同じ基本データ型である必要があります。データ型を指定しない場合、デフォルトで logical 型になります。また、任意の型の空のベクトルを宣言することも可能です。

R

another_vector <- vector(mode='character', length=3)
another_vector

出力

[1] "" "" ""

あるオブジェクトがベクトルかどうかを確認することもできます:

R

str(another_vector)

出力

 chr [1:3] "" "" ""

このコマンドのやや難解な出力は、このベクトルに含まれる基本データ型(この場合は chr、文字型)を示し、ベクトル内の要素数(この場合は [1:3])、および実際に含まれる要素(この場合は空の文字列)を示します。同様に次のコマンドを実行すると、

R

str(cats$weight)

出力

 num [1:3] 2.1 5 3.2

cats$weight もベクトルであることがわかります。R のデータフレームに読み込まれる列はすべてベクトルです。これが、R が列内のすべての要素を同じ基本データ型に強制する理由の根本です。

討論 1

なぜ R は列に含まれるデータに対してこれほど厳格なのでしょうか? この厳格さは私たちにどのように役立つのでしょうか?

列内のすべてのデータが同じであることで、データに対して単純な仮定を行うことができます。たとえば、列の 1 つの要素を数値として解釈できるなら、列内のすべての要素を数値として解釈できます。そのため、毎回確認する必要がなくなります。この一貫性こそが、人々が「クリーンデータ」と呼ぶものです。長い目で見ると、この厳格な一貫性は R におけるデータ操作を非常に簡単にしてくれます。

ベクトルを結合する際の型の強制変換

明示的な内容を持つベクトルを c() 関数で作成できます:

R

combine_vector <- c(2,6,3)
combine_vector

出力

[1] 2 6 3

これまで学んだ内容を考えると、次のコードは何を生成すると思いますか?

R

quiz_vector <- c(2,6,'3')

これは 型の強制変換 と呼ばれるもので、予想外の結果をもたらすことがあり、基本データ型と R がそれをどのように解釈するかを理解する必要があります。R は、異なる型(ここでは doublecharacter)が単一のベクトルに結合される場合、それらをすべて同じ型に強制します。例を見てみましょう:

R

coercion_vector <- c('a', TRUE)
coercion_vector

出力

[1] "a"    "TRUE"

R

another_coercion_vector <- c(0, TRUE)
another_coercion_vector

出力

[1] 0 1

型の階層

型の強制変換ルールは次の通りです:
logical -> integer -> double (“numeric”) -> complex -> character
この矢印は「変換される」と読めます。たとえば、logicalcharacter を結合すると、結果は character に変換されます:

R

c('a', TRUE)

出力

[1] "a"    "TRUE"

character ベクトルは、印刷時にクォートで囲まれていることで簡単に認識できます。

逆方向の強制変換を試みる場合は、as. 関数を使用します:

R

character_vector_example <- c('0','2','4')
character_vector_example

出力

[1] "0" "2" "4"

R

character_coerced_to_double <- as.double(character_vector_example)
character_coerced_to_double

出力

[1] 0 2 4

R

double_coerced_to_logical <- as.logical(character_coerced_to_double)
double_coerced_to_logical

出力

[1] FALSE  TRUE  TRUE

R が基本データ型を他の型に強制する際に驚くべきことが起こる場合があります!型の強制変換の細かい点はさておき、重要なのは:データが予想していた形式と異なる場合、それは型の強制変換が原因である可能性が高いです。ベクトルやデータフレームの列内のすべてのデータが同じ型であることを確認してください。さもなければ、予想外の問題が発生する可能性があります!

しかし、強制変換は非常に便利な場合もあります!たとえば、cats データの likes_catnip 列は数値型ですが、実際には 1 と 0 がそれぞれ TRUEFALSE を表しています。このデータには logical 型を使用すべきです。この型は TRUE または FALSE の 2 状態を持ち、データの意味に完全に一致します。この列を logical に「強制変換」するには、as.logical 関数を使用します:

R

cats$likes_catnip

出力

[1] 1 0 1

R

cats$likes_catnip <- as.logical(cats$likes_catnip)
cats$likes_catnip

出力

[1]  TRUE FALSE  TRUE

チャレンジ 1

データ分析の重要な部分は、入力データのクリーンアップです。入力データがすべて同じ形式(例:数値)であることを知っていると、分析がはるかに簡単になります!型の強制変換に関する章で扱った猫のデータセットをクリーンアップしましょう。

コードテンプレートをコピー

RStudio で新しいスクリプトを作成し、以下のコードをコピー&ペーストしてください。その後、以下のタスクを参考にギャップ(______)を埋めてください。

# データを読み込み
cats <- read.csv("data/feline-data_v2.csv")

# 1. データを表示
_____

# 2. 表の概要をデータ型と共に表示
_____(cats)

# 3. "weight" 列の現在のデータ型 __________。
#    正しいデータ型は: ____________。

# 4. 4 番目の "weight" データポイントを指定された 2 つの値の平均に修正
cats$weight[4] <- 2.35
#    効果を確認するためにデータを再表示
cats

# 5. "weight" を正しいデータ型に変換
cats$weight <- ______________(cats$weight)

#    自分でテストするために平均を計算
mean(cats$weight)

# 正しい平均値(NA ではない)が表示されたら、演習は完了です!

タスクの手順

1. データを表示する

最初のステートメント(read.csv(...))を実行します。その後、データをコンソールに表示します。

任意の変数の内容を表示するには、その名前を入力します。

チャレンジ 1.1 の解答

2 つの正しい解答:

R

cats

出力

    coat weight likes_catnip
1 calico    2.1         TRUE
2  black    5.0        FALSE
3  tabby    3.2         TRUE

R

print(cats)

出力

    coat weight likes_catnip
1 calico    2.1         TRUE
2  black    5.0        FALSE
3  tabby    3.2         TRUE

2. データ型の概要を表示する

データ型はデータ自体と同じくらい重要です。以前見た関数を使用して、cats テーブルのすべての列のデータ型を表示します。

「データ型」の章で、データ型を表示する 2 つの関数を見ました。1 つはデータ型の名前だけを出力し、もう 1 つは短い形式のデータ型と最初の値を出力しました。ここでは後者を使用します。

チャレンジ 1.2 の解答

R

str(cats)

出力

'data.frame':	3 obs. of  3 variables:
 $ coat        : chr  "calico" "black" "tabby"
 $ weight      : num  2.1 5 3.2
 $ likes_catnip: logi  TRUE FALSE TRUE

3. 必要

なデータ型はどれですか?

表示されるデータ型は、このデータ(猫の体重)には適していません。必要なデータ型はどれですか?

  • なぜ read.csv() 関数は正しいデータ型を選ばなかったのでしょうか?
  • コメントのギャップに猫の体重に適したデータ型を埋めてください!

型の階層 のセクションに戻り、利用可能なデータ型を確認してください。

チャレンジ 1.3 の解答

  • 体重は連続スケール(実数)で表されます。この場合の R のデータ型は “double”(“numeric” とも呼ばれます)です。
  • 4 行目の値は “2.3 or 2.4” であり、数値ではなく英単語が含まれています。そのため、“character” 型が選ばれます。同じ列内のすべての値が同じデータ型である必要があるため、列全体がテキスト型になっています。

4. 問題のある値を修正する

問題のある 4 行目に新しい体重値を割り当てるコードが提供されています。実行する前に考えてみてください。この例のように数値を割り当てた後のデータ型はどうなりますか? 実行後にデータ型を確認して、自分の予測が正しいか確認してください。

2 つの異なるデータ型が組み合わされた場合の型の階層を再確認してください。

チャレンジ 1.4 の解答

列 “weight” のデータ型は “character” です。割り当てるデータ型は “double” です。異なるデータ型を組み合わせると、次の階層でより高いデータ型に変換されます:

logical < integer < double < complex < character

したがって、列はまだ “character” 型です!これを “double” 型に手動で変換する必要があります。

5. 列 “weight” を正しいデータ型に変換する

猫の体重は数値です。しかし、列にはまだ適切なデータ型が設定されていません。この列を浮動小数点数に強制変換してください。

データ型を変換する関数は as. で始まります。このスクリプトの上部で関数を確認するか、RStudio のオートコンプリート機能を使用してください。 “as.” と入力し、TAB キーを押します。

チャレンジ 1.5 の解答

歴史的な理由で、2 つの同義の関数があります:

R

cats$weight <- as.double(cats$weight)
cats$weight <- as.numeric(cats$weight)

基本的なベクトル関数

c() 関数を使用すると、既存のベクトルに新しい要素を追加することができます:

R

ab_vector <- c('a', 'b')
ab_vector

出力

[1] "a" "b"

R

combine_example <- c(ab_vector, 'SWC')
combine_example

出力

[1] "a"   "b"   "SWC"

また、数列を生成することも可能です:

R

mySeries <- 1:10
mySeries

出力

 [1]  1  2  3  4  5  6  7  8  9 10

R

seq(10)

出力

 [1]  1  2  3  4  5  6  7  8  9 10

R

seq(1, 10, by=0.1)

出力

 [1]  1.0  1.1  1.2  1.3  1.4  1.5  1.6  1.7  1.8  1.9  2.0  2.1  2.2  2.3  2.4
[16]  2.5  2.6  2.7  2.8  2.9  3.0  3.1  3.2  3.3  3.4  3.5  3.6  3.7  3.8  3.9
[31]  4.0  4.1  4.2  4.3  4.4  4.5  4.6  4.7  4.8  4.9  5.0  5.1  5.2  5.3  5.4
[46]  5.5  5.6  5.7  5.8  5.9  6.0  6.1  6.2  6.3  6.4  6.5  6.6  6.7  6.8  6.9
[61]  7.0  7.1  7.2  7.3  7.4  7.5  7.6  7.7  7.8  7.9  8.0  8.1  8.2  8.3  8.4
[76]  8.5  8.6  8.7  8.8  8.9  9.0  9.1  9.2  9.3  9.4  9.5  9.6  9.7  9.8  9.9
[91] 10.0

ベクトルについていくつかの質問をすることもできます:

R

sequence_example <- 20:25
head(sequence_example, n=2)

出力

[1] 20 21

R

tail(sequence_example, n=4)

出力

[1] 22 23 24 25

R

length(sequence_example)

出力

[1] 6

R

typeof(sequence_example)

出力

[1] "integer"

ベクトルの特定の要素を取得するには、角括弧記法を使用します:

R

first_element <- sequence_example[1]
first_element

出力

[1] 20

特定の要素を変更するには、角括弧を矢印の右側に使用します:

R

sequence_example[1] <- 30
sequence_example

出力

[1] 30 21 22 23 24 25

チャレンジ 2

1 から 26 までの数を含むベクトルを作成します。その後、このベクトルを 2 倍にします。

R

x <- 1:26
x <- x * 2

リスト

次に紹介するデータ構造は list です。リストは他のデータ型よりもシンプルで、何でも入れることができるのが特徴です。ベクトルでは要素の基本データ型を統一する必要がありましたが、リストは異なるデータ型を持つことができます:

R

list_example <- list(1, "a", TRUE, 1+4i)
list_example

出力

[[1]]
[1] 1

[[2]]
[1] "a"

[[3]]
[1] TRUE

[[4]]
[1] 1+4i

str() を使用してオブジェクトの構造を表示すると、すべての要素のデータ型を確認できます:

R

str(list_example)

出力

List of 4
 $ : num 1
 $ : chr "a"
 $ : logi TRUE
 $ : cplx 1+4i

リストの用途は何でしょうか?例えば、異なるデータ型を持つ関連データを整理できます。これは、Excel のスプレッドシートのように複数の表をまとめるのと似ています。他にも多くの用途があります。

次の章で、驚くかもしれない別の例を紹介します。

リストの特定の要素を取得するには 二重角括弧 を使用します:

R

list_example[[2]]

出力

[1] "a"

リストの要素には 名前 を付けることもできます。名前を値の前に等号で指定します:

R

another_list <- list(title = "Numbers", numbers = 1:10, data = TRUE )
another_list

出力

$title
[1] "Numbers"

$numbers
 [1]  1  2  3  4  5  6  7  8  9 10

$data
[1] TRUE

これにより 名前付きリスト が生成されます。これで新しいアクセス方法が追加されます!

R

another_list$title

出力

[1] "Numbers"

名前


名前を使用すると、要素に意味を持たせることができます。これにより、データだけでなく説明情報も持つことができます。これはオブジェクトに貼り付けられるラベルのような メタデータ です。R ではこれは 属性 と呼ばれます。属性により、オブジェクトをさらに操作することが可能になります。ここでは、定義された名前で要素にアクセスすることができます。

名前を使用してベクトルやリストにアクセスする

名前付きリストの生成方法はすでに学びました。名前付きベクトルを生成する方法も非常に似ています。以前このような関数を見たことがあるはずです:

R

pizza_price <- c( pizzasubito = 5.64, pizzafresh = 6.60, callapizza = 4.50 )

しかし、要素の取得方法はリストとは異なります:

R

pizza_price["pizzasubito"]

出力

pizzasubito
       5.64 

リストのアプローチは機能しません:

R

pizza_price$pizzafresh

エラー

Error in pizza_price$pizzafresh: $ operator is invalid for atomic vectors

このエラーメッセージを覚えておくと役立ちます。同じようなエラーに遭遇することが多いですが、これはリストと勘違いしてベクトルの要素にアクセスしようとした場合に発生します。

名前の取得と変更

名前だけに興味がある場合は、names() 関数を使用します:

R

names(pizza_price)

出力

[1] "pizzasubito" "pizzafresh"  "callapizza" 

ベクトルの要素にアクセスしたり変更したりする方法を学びました。同じことが名前についても可能です:

R

names(pizza_price)[3]

出力

[1] "callapizza"

R

names(pizza_price)[3] <- "call-a-pizza"
pizza_price

出力

 pizzasubito   pizzafresh call-a-pizza
        5.64         6.60         4.50 

チャレンジ 3

  • pizza_price の名前のデータ型は何ですか?str() または typeof() 関数を使用して調べてください。

オブジェクトの名前を取得するには、その名前を names(...) で囲みます。同様に、名前のデータ型を取得するには、全体をさらに typeof(...) で囲みます:

typeof(names(pizza))

または、コードをわかりやすくするために新しい変数を使用します:

n <- names(pizza)
typeof(n)

チャレンジ 4

既存のベクトルやリストの一部の名前を変更する代わりに、オブジェクトのすべての名前を設定することも可能です。次のコード形式を使用します(すべての大文字部分を置き換えてください):

names( OBJECT ) <-  CHARACTER_VECTOR

アルファベットの各文字に番号を割り当てるベクトルを作成しましょう!

  1. 1 から 26 の数列を持つ letter_no というベクトルを作成します。
  2. R には LETTERS という組み込みオブジェクトがあります。これは A から Z までの 26 文字を含むベクトルです。この 26 文字を letter_no の名前として設定します。
  3. letter_no["B"] を呼び出して、値が 2 であることを確認してください!
letter_no <- 1:26   # or seq(1,26)
names(letter_no) <- LETTERS
letter_no["B"]

データフレーム


このレッスンの冒頭でデータフレームについて簡単に触れましたが、それはデータの表形式を表しています。例として示した猫のデータフレームについては詳細に掘り下げていませんでした:

R

cats

出力

    coat weight likes_catnip
1 calico    2.1         TRUE
2  black    5.0        FALSE
3  tabby    3.2         TRUE

ここで少し驚くべきことに気づくかもしれません。次のコマンドを実行してみましょう:

R

typeof(cats)

出力

[1] "list"

データフレームが「内部的にはリストのように見える」ことがわかります。以前、リストについて次のように説明しました:

リストは異なる型のデータを整理するためのもの

データフレームの列は、それぞれが異なる型のベクトルであり、同じ表に属することで整理されています。

データフレームは実際にはベクトルのリストです。データフレームが特別なのは、すべてのベクトルが同じ長さでなければならない点です。

この「特別さ」はどのようにオブジェクトに組み込まれているのでしょうか?R がそれを単なるリストではなく、表として扱うのはなぜでしょう?

R

class(cats)

出力

[1] "data.frame"

クラス は名前と同様に、オブジェクトに付加される属性です。この属性は、そのオブジェクトが人間にとって何を意味するのかを示します。

ここで疑問に思うかもしれません:なぜオブジェクトの型を判断するための関数がもう一つ必要なのでしょうか?すでに typeof() がありますよね?
typeof() はオブジェクトがコンピュータ内でどのように構築されているかを教えてくれます。一方、class() はオブジェクトの人間にとっての意味を示します。したがって、typeof() の出力は R で固定されています(主に 5 種類のデータ型)が、class() の出力は R パッケージによって多様で拡張可能です。

cats の例では、整数型、倍精度数値型、論理型の変数が含まれています。すでに見たように、データフレームの各列はベクトルです:

R

cats$coat

出力

[1] "calico" "black"  "tabby" 

R

cats[,1]

出力

[1] "calico" "black"  "tabby" 

R

typeof(cats[,1])

出力

[1] "character"

R

str(cats[,1])

出力

 chr [1:3] "calico" "black" "tabby"

一方、各行は異なる変数の観測値であり、それ自体がデータフレームであり、異なる型の要素で構成されることができます:

R

cats[1,]

出力

    coat weight likes_catnip
1 calico    2.1         TRUE

R

typeof(cats[1,])

出力

[1] "list"

R

str(cats[1,])

出力

'data.frame':	1 obs. of  3 variables:
 $ coat        : chr "calico"
 $ weight      : num 2.1
 $ likes_catnip: logi TRUE

チャレンジ 5

データフレームから変数、観測値、要素を取得する方法はいくつかあります:

  • cats[1]
  • cats[[1]]
  • cats$coat
  • cats["coat"]
  • cats[1, 1]
  • cats[, 1]
  • cats[1, ]

これらの例を試して、それぞれが何を返すのかを説明してください。

ヒント: 返されるものを調べるには、typeof() 関数を使用してください。

R

cats[1]

出力

    coat
1 calico
2  black
3  tabby

データフレームはベクトルのリストと考えられます。単一ブラケット [1] はリストの最初のスライスを別のリストとして返します。この場合、それはデータフレームの最初の列です。

R

cats[[1]]

出力

[1] "calico" "black"  "tabby" 

二重ブラケット [[1]] はリスト項目の内容を返します。この場合、最初の列の内容である character 型のベクトルです。

R

cats$coat

出力

[1] "calico" "black"  "tabby" 

$ を使用して名前で項目にアクセスします。coat はデータフレームの最初の列であり、character 型のベクトルです。

R

cats["coat"]

出力

    coat
1 calico
2  black
3  tabby

単一ブラケット ["coat"] を使用し、インデックス番号の代わりに列名を指定します。例 1 と同様に、返されるオブジェクトは list です。

R

cats[1, 1]

出力

[1] "calico"

単一ブラケットを使用し、行と列の座標を指定します。この場合、1 行目 1 列目の値が返されます。オブジェクトは character 型のベクトルです。

R

cats[, 1]

出力

[1] "calico" "black"  "tabby" 

前の例と同様に単一ブラケットを使用し、行と列の座標を指定しますが、行座標が指定されていません。この場合、R は欠損値をその列のすべての要素として解釈し、ベクトル として返します。

R

cats[1, ]

出力

    coat weight likes_catnip
1 calico    2.1         TRUE

再び単一ブラケットを使用し、行と列の座標を指定しますが、今回は列座標が指定されていません。返される値は 1 行目のすべての値を含む list です。

ヒント: データフレーム列の名前変更

データフレームには列名があり、names() 関数でアクセスできます:

R

names(cats)

出力

[1] "coat"         "weight"       "likes_catnip"

cats の 2 番目の列の名前を変更したい場合は、names(cats) の 2 番目の要素に新しい名前を割り当てます:

R

names(cats)[2] <- "weight_kg"
cats

出力

    coat weight_kg likes_catnip
1 calico       2.1         TRUE
2  black       5.0        FALSE
3  tabby       3.2         TRUE

行列(Matrix)

最後に紹介するのは行列です。ゼロで満たされた行列を宣言してみましょう:

R

matrix_example <- matrix(0, ncol=6, nrow=3)
matrix_example

出力

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    0    0    0    0    0
[2,]    0    0    0    0    0    0
[3,]    0    0    0    0    0    0

行列を特別なものにしているのは dim() 属性です:

R

dim(matrix_example)

出力

[1] 3 6

他のデータ構造と同様に、行列について質問することも可能です:

R

typeof(matrix_example)

出力

[1] "double"

R

class(matrix_example)

出力

[1] "matrix" "array" 

R

str(matrix_example)

出力

 num [1:3, 1:6] 0 0 0 0 0 0 0 0 0 0 ...

R

nrow(matrix_example)

出力

[1] 3

R

ncol(matrix_example)

出力

[1] 6

チャレンジ 6

次のコードの結果はどうなるでしょうか?

R

length(matrix_example)

出力

[1] 18

実行して確認してください。予想は当たりましたか?なぜそのような結果になるのでしょうか?

行列は次元属性を持つベクトルであるため、length は行列内の要素の総数を返します:

R

matrix_example <- matrix(0, ncol=6, nrow=3)
length(matrix_example)

出力

[1] 18

チャレンジ 7

1 から 50 の数値を含む、列数 5、行数 10 の行列を作成します。 デフォルトの動作として、この行列は列ごとに値が埋められますか、それとも行ごとですか? その動作を変更する方法を調べてください。(ヒント:matrix のドキュメントを参照)

R

x <- matrix(1:50, ncol=5, nrow=10)
x <- matrix(1:50, ncol=5, nrow=10, byrow = TRUE) # 行ごとに埋める

チャレンジ 8

このワークショップの次のセクションに対応する 2 つの要素を持つリストを作成します:

  • データ型
  • データ構造

各データ型およびデータ構造の名前を文字型ベクトルに格納してください。

R

dataTypes <- c('double', 'complex', 'integer', 'character', 'logical')
dataStructures <- c('data.frame', 'vector', 'list', 'matrix')
answer <- list(dataTypes, dataStructures)

チャレンジ 9

以下の行列の R 出力を考えてみてください:

出力

     [,1] [,2]
[1,]    4    1
[2,]    9    5
[3,]   10    7

この行列を作成するために使用された正しいコマンドはどれでしょうか?各コマンドを確認し、入力する前に正しいものを考えてください。
他のコマンドでどのような行列が作成されるかを考えてみてください。

  1. matrix(c(4, 1, 9, 5, 10, 7), nrow = 3)
  2. matrix(c(4, 9, 10, 1, 5, 7), ncol = 2, byrow = TRUE)
  3. matrix(c(4, 9, 10, 1, 5, 7), nrow = 2)
  4. matrix(c(4, 1, 9, 5, 10, 7), ncol = 2, byrow = TRUE)

R

matrix(c(4, 1, 9, 5, 10, 7), ncol = 2, byrow = TRUE)

まとめ

  • read.csv を使用して R で表形式データを読み取ります。
  • R の基本データ型は、double、integer、complex、logical、character です。
  • データフレームや行列のようなデータ構造は、リストやベクトルを基にし、いくつかの属性が追加されています。