jnobuyukiのブログ

研究していて困ったことやその解決に関するメモ。同じように困ったあなたのために。twitter ID: @j_nobuyuki

Rのデータフレームから数値変数だけを抜き出したい

今回は,ありそうでなさそうなデータハンドリングに関して,メモ代わりにやり方を共有します。
Rを利用しながらデータ解析を行う際に,データフレームという数値変数も文字列変数も一緒に保存できる形式が便利です。便利なのを良いことに,順序をあまり考慮せずにデータフレームオブジェクトを作ってしまうと...。「20個ある変数の中で,2番めと4番目と5番目と9番目10番目11番目と18番目の変数が数値変数。あとは文字列変数。」といった複雑な状況が生じます。では,このような数値変数と文字列変数がまざったデータフレームオブジェクトから数値変数だけを抜き出す方法を考えてみましょう。

str関数はあまり役に立たない

str関数は,データフレームオブジェクトの中身の変数のクラスを表示してくれます。これを利用できそうな気がするのですが,どうもstr関数は,次の計算に使用可能な出力がありません。なので,結局目で見ながらメモをとることになってしまいます。

is.numeric関数を使いましょう

str関数がうまくいかないので,is.numeric関数を利用します。この関数は,引数として与えたベクトルオブジェクトが数値ベクトルのときにTRUE, そうでなければFALSEを返します。なので,次のようなコードで数値ベクトルかどうかの判断した結果を残せます。

res <- NULL

for  ( i in 1:ncol(data)){

    res <- append(res, is.numeric(data[,i]))    

}

あとは,データフレーム全体から,is.numeric関数の出力結果がTRUEの列番号の変数だけを抜けば良いでしょう。

subsetdata <- data[,which(res == TRUE)]


もっと簡単なやり方やそれを一度にできる関数をご存じの方がいらしたらぜひ教えてください。

R言語で複数のスペースで区切られたデータを読み込む

今回は本当にちょっとしたことですが、ハマる内容なので皆様と共有します。

read.table関数でテキストデータを読み込む

データ分析をするときに、何かのアプリケーションで作成したテキストデータをRに読み込ませることがあります。もっとも汎用的な関数はread.table関数です。この関数では、以下のようにファイル名、区切り文字、変数名ラベルの有無などを設定してRのデータフレーム型のオブジェクトとして読み込みます。

data <- read.table("ファイル名", sep = "", header = TRUE)

上記のうち、sepが区切り文字です。カンマ区切りなら","、タブ区切りなら"\t"にします。header はテキストファイルの1行目に変数名があるならTRUE、ないならFALSEにします。

複数のスペースで区切られたテキストファイルの読み込み

通常は上記のような操作でファイルを読み込めば良いので全く問題ありません。問題は、1つ以上の空白スペースで区切られたテキストファイルを読み込むときです。このようなファイルの場合、テキストファイルの見栄えをよくする都合で、変数間でスペースの数が異なることがしばしばあります。これをいかのような区切り文字にスペースを設定する方法だとうまくいきません。

data <- read.table("ファイル名", sep = " ", header = TRUE)

なぜうまくいかないかというと、上記の方法では区切り文字を「1文字の空白スペース」と指定しているからです。つまりスペースの数+1だけ変数があるとなってしまいます。

sep はデフォルトにすればよい

複数の空白スペースで区切られたファイルは、区切り文字をデフォルト""にするとうまく読み込めます。実は、区切り文字のデフォルトは1つまたは複数の空白スペースなんです。なので、空白スペースで区切られたテキストファイルを読み込むにはsepを設定しない(つまりデフォルト値を使う)または以下のように書けば良いでしょう。

data <- read.table("ファイル名", sep ="", header = TRUE)

R言語の場合、きめ細かく引数を設定するのが上手に使うコツの1つだと思うのですが、たまにはデフォルト値を信用してみるというのも大事なようです。

累積PVが30万を越えました。ありがとうございます。

タイトルの通り、累積のPVが30万を越えました。たくさんの方に検索していただいているのだと思うと、もっと良い記事をたくさん投稿しようと思います。そして、数は少ないのですが、常連で読んでくださる方、これからもどうぞよろしくお願いします。

Videoタグで埋め込まれた動画の再生スピードを変えたい

今回は、ウエブ上に置かれている動画の操作について、ちょっとしたやり方を書きます。自分自身へのメモ代わりです。

動画の再生

インターネット上の動画コンテンツは以前はFlashというプラグインを利用して閲覧することが多かったのですが、最近はvideoタグというHTML5のオブジェクトとして埋め込まれることが多くなりました。例えばYou Tubeの動画も多くはこのvideoタグとして埋め込まれているようです。そして、動画の内容によっては、少し早く再生したい、または遅く再生したいということがありますよね。 You Tubeには再生スピードをコントロールする機能が付いていますが、0.25倍、0.5倍、1.25倍、1.5倍、2倍といったように「あと少し早くまたはゆっくり」という変更ができません。今回紹介する方法は、任意の倍率で再生スピードを変えられます。

1. 再生したい動画を表示する

まずは再生したい動画を表示しましょう。

2. Consoleウインドウを開く

Chromeでしたら、右上のメニューから「その他のツール」→「デベロッパーツール」をクリックするとConsoleウインドウが開きます。

3. videoタグのplaybackRage属性を上書きする

以下のコードでvideoタグのオブジェクトの再生スピードを変更できます。以下の例では再生スピードを2倍にしています。2を任意の数字にかえることで、好きな再生速度に設定できます。

document.querySelector('video').playbackRate = 2;

これで動画の再生スピードを変えられます。

おまけ

ここまで紹介しておいてから、ここのおまけとして書くのは少しおかしいのですが、実は、このやり方がうまくいかないこともあります。私の場合mac版のChromeで一部のvideoタグに埋め込まれた動画について上記操作をしても何も変更できないことがあります。どうやら、document.querySelector('video')の段階で参照すべきオブジェクトが拾えていないようです。この対処法として、ビデオが再生されている画面を二本指クリック(右クリック)して、「検証」を押すと、上記と同様にデベロッパーツールが開きます。これをしてからだと、上記の操作が思った通りに動きました。うまくいかないという方はこちらも試してみてください。

R言語での変数の型確認の重要性(3)

前回、R言語で変数型を意識した方が良い例として重回帰分析を紹介しました。その投稿を見てくれた知り合いが、自身の失敗談を教えてくれたので、今回はその話をします。

知り合いの話では、「本来数値データとして独立変数に入れるつもりが、なぜかファクター型として読み込まれてしまっていた。回帰分析の出力結果を見たときに、変数の読み込み失敗に気づいたので、ファクター型変数を数量型変数へと変換した。ところが解析結果は結局おかしなものになってしまった。」というものでした。

仮想例による再現

前回の例を参考にしながら、上で書いた状態を再現してみましょう。

まず、従属変数と独立変数として二つの数量型変数をつくります。

set.seed(1)
DV <- rnorm(100)
set.seed(2)
IV <- rnorm(100)
summary(cbind(DV,IV))

次に独立変数が誤ってファクター型変数になってしまった状態を意図的に作ります。

IVc <- factor(IV)
summary(IVc)

ファクター型の変数を独立変数としたおかしな回帰分析の結果を再現してみます。

res.c <- lm(DV ~ IVc)
summary(res.c)

回帰分析を実施した出力が以下のようになり、何かおかしい事に気づきました。

f:id:jnobuyuki:20170202175608p:plain

これは変数の読み込みがおかしいのだと考え、以下のように独立変数を数量型データへと変換します*1
そしてもう一度回帰分析をしてみました。

IVcn <- as.numeric(IVc)
res.cn <- lm(DV ~ IVcn)
summary(res.cn)

f:id:jnobuyuki:20170202175555p:plain
結果を表示すると、一見何の問題もないように見えます。しかし、本来あるべき解析結果と比較すると結果が異なっているのです。

res <- lm(DV ~ IV)
summary(res)

f:id:jnobuyuki:20170202175537p:plain
こうなってしまったのは、ファクター型から数量型へデータを変換するために使ったas.numeric関数が原因です。ただし、これはバグではなく、仕様です。詳しく見てみましょう。

factor型変数のLevels

factor関数は、数量型または文字列型の変数を変換する際に、水準(levels)という出力を作成します。水準には与えられた入力オブジェクトの値の異なりが保存されています。以下の例がわかりやすいと思います。ファクター型に変換すると、"a","b","c"のような文字列のオブジェクトではa,b,cが、1,2,4のような数値のオブジェクトでは1,2,3という水準が割り振られています。

alphabetObject <- c("a","b","c","a","c","b","b")
numberObject <- c(1,2,4,1,4,2,2)

alphabetObject.factor <- factor(alphabetObject)
numberObject.factor<- factor(numberObject)

print(alphabetObject.factor)
print(numberObject.factor)

f:id:jnobuyuki:20170202175522p:plain
次に上記の変数をas.numeric関数を利用して変換してみます。

as.numeric(alphabetObject.factor)
as.numeric(numberObject.factor)

f:id:jnobuyuki:20170202175507p:plain
出力結果は、どちらも1,2,3という数字で構成されています。文字列が割り振られているファクター型の変数は水準の低い方から1,2,3というように数字を割り振られています。また、数値オブジェクトから変換したファクター型の変数でも、水準の低い方から1,2,3と割り振られています。なので、元々の数値オブジェクトは3という値が含まれていないのに、ファクター型に変換したものを再び数値型に変換すると3という値が含まれています。このような変換の仕様によって、回帰分析の値の中身が変わってしまっていたのでした。これを確かめるため、回帰分析の独立変数について最初の変数と、変換をした後の変数のそれぞれについて最初の6個の値をみてみましょう。

#最初の変数
head(IV)
#ファクター型に変換した変数
head(IVc)
#再び数値型に変換した変数
head(IVcn)

f:id:jnobuyuki:20170202175453p:plain
このように途中まで一見して同じ値の変数になっているので、特に注意が必要です。

対処法: 一旦文字列にしてから、数量データに変換する

では、何らかの理由でファクター型に変換されてしまった変数を、値を変えることなく再び数値型の変数にするにはどうすればよいのでしょうか。実は、直接数値型に戻さずに、一旦文字列型に戻してから、数値型に変換すると値を変えずに数値型オブジェクトに変換できます。

#一旦文字列型に変換
IVcch <- as.character(IVc)
#文字列型の変数を数値型変数に変換
IVcchn <- as.numeric(IVcch)

#最初の変数の最初の6個の値
head(IV)
#変換後の変数の最初の6個の値
head(IVcchn)

f:id:jnobuyuki:20170202175435p:plain

*1:今回は変数の型を変換したことが明示的に示されるように別の変数への代入という方法を取っています。このままだとメモリを解放しないまま解析が進んでしまうので、サイズの大きなデータでは解析が進むにしたがってメモリの問題が深刻になることもあります。これを防ぐには、もう使わない変数をrm関数で削除したり、同じ変数名のまま上書きしていくなどの処理が有効です。

R言語での変数の型確認の重要性(2)

前回、R言語では変数の型を明示的にしていしないので、注意が必要だという投稿をしました。
今回は、型変換に気をつけたほうが良い例として回帰分析をとりあげます。

回帰分析

回帰分析は、ある変数を別の変数で予測に用います。予測に使用する変数の値に適当な重み付けをして、なるべく予測される値に近づけようとするイメージです。予測モデルは、典型的に次のような方程式で表されます。

予測される変数 = 切片 + 係数 * 予測する変数 + 誤差

回帰分析の詳細は、また別の機会にとりあげます。

予測される変数と予測される変数の性質

一般的な回帰分析であれば、予測する変数、予測される変数ともに連続的な量的データを用います。R言語の型で言えば、numeric です*1。しかし、回帰分析はカテゴリーデータを数値に変換して*2、解析に加えられます。そしてR言語のlm関数は、カテゴリーデータの数値変換を**勝手に**やってくれます。「勝手に」カテゴリー変数を前提とした解析を行うので、エラーが出ません。出力を注意深く見ることでこれがわかります。では仮想的なデータを使って、実際にみてみましょう。

まずは、データを用意します。

DV <- rnorm(100)
IV <- sample(1:100,100, replace = TRUE)

上のコードを実行するとDVという変数には平均0、標準偏差1の正規分布からランダムに生成された100の数値が保存されます。また、IDには1から100までの整数がランダムに100保存されます。どちらも数量データです。これらのデータを利用して回帰分析を行うには以下のコードを実行します。

res_lm <- lm(DV~IV)
summary(res_lm)

ここでIVが何らかの理由で、カテゴリーデータになってしまった状況を想定します。変換したデータをIVcとして回帰分析をしてみます。

res_lmc <- lm(DV ~ IVc)
summary(res_lmc)

では二つの回帰分析の出力結果を比べてみましょう。最初にどちらも数量データの回帰分析の出力結果は以下のようになります。
f:id:jnobuyuki:20170127151728p:plain
図のなかで(intercept)の横に書いてある数字が切片の推定値です。その下のIVの横にあるのがIVについての係数の推定値です。ここでは切片や係数の有意性については特に問題にしません。

では、次にカテゴリーデータとして扱われているIVcを使った回帰分析の結果を見てみましょう。
f:id:jnobuyuki:20170127151752p:plain
一見してわかるように、たくさんの推定値が並んでいます。実は表示されている画像は全体の半分くらいです。このようになってしまうのは、IVがカテゴリーデータとして扱われているためです。どういうことかというと、カテゴリデータが独立変数にある場合は、ある基準となる水準からのその他のそれぞれのデータポイントまでの際が、別のものとして推定されるのです。それで、たくさんの係数の推定値が表示されています。

上記を見てわかるように、ちょっとしたコーディング方法の違いでも、出力結果の意味するところは違います。上記のような出力はかなり目立つので、気づいたらすぐに、独立変数の型をstr関数やclass関数で調べてみましょう。

*1:回帰分析には様々なバリエーションがあります。例えば、予測される変数が「はい・いいえ」のような2値データの場合はロジスティック回帰になります。また、予測される変数は量的データ、予測する変数が全てカテゴリーデータの場合は分散分析と見ることができます。そういったバリエーションを包括する概念として線形モデルがあります。

*2:コーディングと呼ばれます。数値の割り当て方は、ダミーコーディングやエフェクトコーディングなどいろいろあります。

Jupyter notebookでRを使う:2017年1月版

今回は、以前紹介したjupyter notebookでRを使うための設定方法を再び紹介します。macを買ったので、新たに設定しようとしたところ以前とはだいぶやり方が違ったので、2017年1月版として紹介します。

今回のインストール環境

  • OS: macOS Sierra 10.12.2
  • python 3.5.2
  • R 3.3.2
  • jupyter 4.2.0

anacondaのインストールが便利

前回jupyterを設定したときは以下のように順番にインストールを進めました。

今回はanacondaというpython用の環境構築パッケージをインストールするだけです。これでjupyterのインストールまでが済んでしまいます。以下のサイトからご自分のOSにあったものをダウンロードしてインストールできます。

Download Anaconda Now! | Continuum

Rで必要なパッケージをインストールします。

RguiかRStudioを起動して、以下の関数を実行しましょう。

install.packages(c('repr', 'IRdisplay', 'crayon', 'pbdZMQ', 'devtools'))

最後にjupyterにR kernelを設定します。

あとはjupyterからR kernelを使えるように設定するだけですが、ここで1つだけ大事なポイントがあります。
以下のコードはRguiや RStudioからではなく、ターミナルから行ってください。そうしないとpythonがR kernelの位置を特定できないようです。
ターミナルでRのコードを実行する際には、最初にターミナルで大文字のRと入力します。するとターミナル内でRが起動しますので、以下のコードを実行してください。

devtools::install_github('IRkernel/IRkernel')
IRkernel::installspec()  

jupyter notebook with R kernelを起動

jupyter notebookを起動するにはターミナルで以下のコードを実行します。

jupyter notebook

これでいつも使っているブラウザが起動して、jupyter notebookのページが表示されるはずです。前回の設定のときに比べてとても簡単になりました。

2017年3月16日追記

Anacondaの最新版4.3.0でjupyter notebookを起動するとプレゼンテーション用のプラグインが実行できないエラーが発生しています。今の所、一つ前のバージョン4.2.0のanacondaをインストールすることをお勧めします。