June 2019
Volume 34 Number 6
[人工知能]
R を使用したデータの探索
Frank La Vigne 氏 | 2019 年 6 月 | サンプル コードのダウンロード
人工知能に関する最初のコラム以降、ご紹介したすべてのサンプル コードでは Python を使用していました。これは、現在のところ Python がデータ サイエンスと AI の言語として主流になっているからです。しかし、これは唯一の存在というわけではなく、Scala や R などの言語がこの分野で頭角を現してきました。さらに別のプログラミング言語をなぜ学ぶ必要があるのかといぶかしく思う開発者の皆様には、Java、C#、Visual Basic、Python、Perl にわたる私の経歴の中で、R には私がどこでも経験したことのない側面があることをお伝えします。R はデータ サイエンスの分野で読者が出会うことの多い言語ですから、この機会に探索しておく価値があると思います。
R そのものは、1970 年代にベル研究所で統計処理のために作成された S プログラミング言語を実装したものです。S は、その当時、統計処理に FORTRAN を使用していた開発者向けに対話型エクスペリエンスを提供するために設計されました。今日では対話型のプログラミング環境は当然のように見なされていますが、当時としては革新的でした。
R は、1992 年にニュージーランドのオークランド大学で Ross Ihaka 氏と Robert Gentleman 氏が発案したもので、作成者たちの名のイニシャルから名前が取られましたが、S という名前にもかけてあります。バージョン 1.0.0 の R は 2000 年にリリースされ、組み込みの統計的アルゴリズムが非常に多いこともあり、研究室で幅広く採用されてきました。関数と拡張機能パッケージを使用して簡単に拡張も可能です。
R に関する安定した開発者コミュニティが生まれ、R パッケージの最も人気のあるリポジトリは Comprehensive R Archive Network (CRAN) です。CRAN には、ベイジアン発生予測から、高分解能フロー インフュージョン質量分析のスペクトル処理まで、何でもカバーするさまざまなパッケージがあります。CRAN で入手可能な R パッケージの完全な一覧は、オンラインで bit.ly/2DGjuEJ をご覧ください。R と CRAN は、あらゆるデータ サイエンスまたは科学研究プロジェクト向けに堅牢なツールを提供していると言っても過言ではありません。
R を使ってみる
おそらく R コードを実行する最も簡単な方法は、Azure Notebook サービス上で Jupyter Notebook を使用することです。Jupyter ノートブックについて詳しくは、msdn.com/magazine/mt829269 のトピックにある 2018 年 2 月の私の記事をご覧ください。ただし、今回は、新しいノートブックを作成するときに言語として R を選択してください。R のロゴが、ブラウザー ウィンドウの右上に表示されるはずです。空白セルに次のコードを入力して実行します。
# My first R code
print("hello world")
x <- 3.14
y = 1.21
x
y
出力には、伝統的な "hello world" というあいさつと、3.14 と 1.21 という値が表示されます。ここまでは、ソフトウェア開発者にとって新しいことでもユニークなことでもありません。代入演算子として、一般的に使用される等号だけでなく、"<-" も使用できる点にご注目ください。どちらも構文的な機能は等価です。また、# 文字以降はコメントになり、行の残りの部分に適用されます。
ベクターは、数値データ、文字データ、論理データを保持できる 1 次元配列です。c 関数で作成します。c は "combine" (結合) を表します。 以下を新しいセルに入力して実行します。
num_vec <- c(1,2,3.14) # numeric vector
char_vec <- c("blog","podcast","livestream") # character vector
bool_vec <- c(TRUE,TRUE,FALSE) #logical vector
#print out values
num_vec
char_vec
bool_vec
表示される値は、コードで設定した値と一致しているはずです。ここで、ベクターに複数の型をミックスして入れることはできるのだろうかと思うかもしれません。以下のコードを新しいセルに入力してください。
mix_vec <- c(1,"lorem ispum",FALSE)
mix_vec
コードは確かに実行されますが、観察力の鋭い読者は、ベクター内の各要素が単一引用符で囲まれていることにお気付きでしょう。これは、値が文字値に変換されたことを示しています。R には、特定の変数の型をチェックするための typeof 関数があります。次のコードを入力して、これまでに作成したベクターを検査してください。
typeof(num_vec)
typeof(char_vec)
typeof(bool_vec)
typeof(mix_vec)
知っておくと便利なもう 1 つの関数は ls です。この関数は、現在の作業環境にあるすべてのオブジェクトを表示します。新しいセルに "ls()" と入力して実行すると、出力には、先ほど定義した 4 つのベクターと共に、最初のセルで定義した x および y 変数が表示されます。
データを操作する
R 言語の真の実力とエレガントな特徴を体験する早道は、実際にデータの探索と操作を実行してみることです。R では、簡単にデータセットを読み込んで、ディメンション、構造、統計的なプロパティをすばやく把握できます。次のいくつかの例では、私にとって身近で重要なデータセットである、私のブログ アクティビティに関する基本的な統計情報を使用します。私は 2004 年以来、技術ブログを運営して維持管理しており、各月に投稿した頻度について基本的な統計情報を保持しています。さらに、各月の日数と、1 日あたりの平均投稿数 (PPD) を追加してあります。PPD は、特定の月の投稿数をその月の日数で割った値です。その CSV ファイルを、Azure Notebook サービスのプロジェクト ライブラリに置きました。bit.ly/2V76d2G にあります。
新しいセルに次のコードを入力して、データを R のデータ フレーム (列に変数、行に観測値を入れた表形式のデータ構造体) に読み込んでから、head および tail 関数を使用してそれぞれ最初の 6 レコードと最後の 3 レコードを表示します。
postData <- read.csv(file="franksworldposts.csv", header=TRUE, sep=",")
head(postData)
tail(postData, 3)
str 関数を使用すると、DataFrame の基本的な構造とデータ型を表示できます。以下のコードを新しいセルに入力してください。
str(postData)
出力には、DataFrame に 183 個の観測値 (つまり、行) があり、4 つの変数 (つまり、列) で構成されていることが表示されます。Posts および Days.in.Month 変数は整数ですが、PPD は数値型です。Month 変数は、183 個のレベルを持つ因子です。因子とは、統計におけるカテゴリ変数に対応するデータ型です。因子は、Python Pandas の categorical と機能的に等価で、文字列または整数にすることができます。これは、限られた数の一意の値 (R の用語で言うと、レベル) を持つ変数に最適です。この DataFrame では、Month フィールドは、2004 年 2 月から 2019 年 4 月までの月を表しています。日付は繰り返されないため、重複したカテゴリ値はありません。
これで私のデータを読み込めたので、並べ替えてクエリを実行すれば、さらに探索できます。おそらく、いくつか分析情報を得ることができます。たとえば、私のブログで最も生産性が高かった上位 10 か月を表示するには、Posts 列を降順に並べ替えることでできます。それを行うには、以下のコードを新しいセルに入力して実行します。
sortedPostData <- postData[order(-postData$Posts),]
head(sortedPostData, 10)
最もアクティブな上位 10 か月はすべて過去 3 年以内でした。データセットをさらに探索するために、100 件以上の投稿があった月を判別するフィルター操作を実行できます。R では subset 関数でちょうどそのことを実行できます。次のコードを入力して、このフィルターを適用し、over100 という名前の新しい DataFrame に出力を代入します。
over100 <- subset(postData, subset = Posts >= 100)
over100
結果は、先ほどの上位 10 件の出力に似ています。行数を確認するには、次のように、DataFrame 内の行数をカウントする nrow 関数を使用します。
nrow(over100)
この出力から、特定の月に 100 件以上のブログ投稿があったのが 11 行であることがわかります。100 件の投稿のあった 2005 年 5 月は第 11 位で、惜しくも上位 10 か月の最もアクティブな月を逃しました。その後の 11 年間は、1 か月に 100 件の投稿というマイルストーンに再び到達することがありませんでした。ブログの開始時に投稿が集中した後フェードアウトし、もう一度盛り返したというパターンがあるのでしょうか。もう少し詳しくデータを見てみましょう。
ちょうど良い機会なので、DataFrame 内の個々の行と列を表示する方法について説明しておきます。たとえば、DataFrame の最初の行を表示するには、次のコードを入力すれば行全体の内容が表示されます。
postData[1,]
DataFrame のインデックスは 1 から始まっており、他のほとんどのプログラミング言語のように 0 からではないことにご注意ください。最初の行の Posts フィールドだけを表示するには、次のコードを入力します。
postData[1,2]
Posts フィールドのすべての値を表示するには、次のコード行を使用します。
postData[,2]
または、次の構文を使用して、名前に基づいて列を表示することもできます。次のコード行を入力し、その出力が先ほどの行からの出力と一致していることをご確認ください。
postData$Posts
R のルーツは統計処理なので、データの基本的な形状やプロパティを表示する多くの組み込み関数が用意されています。次のコードを使用して、Posts 列のデータの理解を深めましょう。
mean(postData$Posts)
max(postData$Posts)
min(postData$Posts)
summary(postData$Posts)
次に、これを PPD 列と比較してみましょう。次のように入力します。
mean(postData$PPD)
max(postData$PPD)
min(postData$PPD)
summary(postData$PPD)
表示されたデータからわかるとおり、15 年間の中で 1 か月あたりの投稿数は 1 件から 225 件まで変動しています。最初の 1 年だけを調査するにはどうしたらよいでしょうか。ブログ投稿の最初の年のレコードについてのみ Posts および PPD フィールドの統計概要を表示するには、次のコードを入力します。
postData[1:12,]
summary(postData[1:12,2]) # Posts
summary(postData[1:12,4]) # PPD
このように数値は多くのことを語りますが、グラフを使用すると傾向とパターンについてより多くのことが明らかになります。幸い、R には、豊富なグラフ プロット機能が組み込まれています。それらを調べてみましょう。
データを視覚化する
R でプロットを作成する方法は非常にシンプルで、1 行のコードで実行できます。最初の年の投稿数と PPD 値を使って始めてみましょう。このコードを以下に示します。
plot(postData[1:12,2], xlab="Month Index", ylab="Posts",
main="Posts in the 1st Year")
plot(postData[1:12,4], xlab="Month Index", ylab="PPD",
main="PPD in the 1st Year")
出力は図 1 のようになるはずです。
図 1 Posts および PPD 列のプロット
グラフを見ると、ブログの最初の年、投稿アクティビティは着実に増加し、3 番目と 6 番目の月の間に急成長を遂げました。夏の終わりに落ち込んだ後、2004 年は大幅に増加して終わりました。さらに、グラフは、1 か月の投稿数と 1 日あたりの投稿数の間に強い相関関係があることを示しています。これは直感的にもわかることですが、グラフの形で表示してみると興味深いものです。
ここで、15 年間全体にわたってブログ投稿のグラフを表示して、より長い期間にパターンが現れるかどうか見てみましょう。次のコードを入力して、期間全体をグラフにします。
plot(postData[,2], xlab="Month Index", ylab="Posts",
main="All Posts")
図 2 に示した結果を見ると、はっきりとしたパターンではありませんが、傾向が現れています。ブログ アクティビティは活発な状態で始まりましたが、少しずつ減退し、30 か月ほど前からもう一度上昇しています。最後の傾向は明らかに上昇です。また、顕著な外れ値が 1 つあります。
図 2 15 年間の投稿
相関関係マトリックス
前に、Posts 列と PPD 列の間の相関関係について言及しました。R には、相関関係マトリックス (変数間の相関係数を示したテーブル) を表示する組み込み関数があります。テーブル内の各セルは、2 つの変数間の相関関係を示します。
相関関係マトリックスでは、データがすばやく集計され、変数間の関係が明らかになります。値が 1 に近いほど密接な相関関係を持ち、0 に近いほど相関関係は低くなります。負の値は、負の相関関係を示します。postData DataFrame の相関マトリックスを表示するには、まず数値フィールドを分離して独自の DataFrame に入れた後、cor 関数を呼び出します。以下のコードを新しいセルに入力して実行します。
postsCor <- postData[, c(2, 3 ,4)]
cor(postsCor)
この出力から、Posts と PPD の間には完璧に近い相関関係があり、Days.In.Month には PPD に対して若干の負の相関関係があることがわかります。
まとめ
R の構文とアプローチには従来のプログラミング言語と異なる部分がありますが、データ ラングリングと数学的な処理のための洗練されたソリューションになると私は思います。データ サイエンスでのキャリア構築に取り組んでいるソフトウェア エンジニアにとって、R は伸ばすべき重要なスキルです。
この記事では、R プログラミング言語の基礎の一部を取り上げました。組み込み関数を使用してデータを DataFrame に読み込んで探索し、統計から分析情報を収集し、グラフをプロットする方法を示しました。実のところ、この記事のすべての内容は "base" R と言えるもので記述したため、何らかのサード パーティ製パッケージに依存することはありません。ただし、一部の R ユーザーが好んで使用する"tidyverse" スイートのパッケージでは、異なるスタイルが使用されています。それについては、次回のコラムで説明しましょう。
Frank La Vigne氏は、Microsoft で AI テクノロジ ソリューションの専門家として働き、企業が分析と AI によってデータからより多くの価値を引き出してより多くの事柄を実現するのを支援しています。また、DataDriven ポッドキャストの共同ホストも努めています。FranksWorld.com (英語) に定期的にブログ記事を投稿し、Frank’s World TV (youtube.com/FranksWorldTV (英語)) という YouTube チャンネルを主催しています。
この記事のレビューに協力してくれた技術スタッフのAndy Leonard 氏、David Smith 氏に感謝します。
David Smith 氏は、人工知能と機械学習のトピックを専門としている Microsoft のクラウド アドボケイトです。2009 年以来、Revolutions ブログ (blog.revolutionanalytics.com) の編集者を務めており、R プログラミング言語に重点を置いてデータ サイエンスのアプリケーションについて定期的に執筆しています。R Consortium の創設メンバーでもあります。David 氏の Twitter は @revodavid でフォローしてください。