いろいろ倉庫

KNIME、EXCEL、R、Pythonなどの備忘録

【R】Rの使い方メモ②(データフレーム)

・お題:Rの基本的な使い方に関して、長くなったので分けて記載することにした。今回はデータフレーム関連。思いついたら随時追加していきたい。

 

・とりあえず、csvを読み込む。

> df<-read.csv("test.csv")
> df
   ID      Name Nenshu Shusshin
1   a    Tanaka    300    Tokyo
2   b      Sato    400    Tokyo
3   c    Suzuki    500 Hokkaido
4   d     Saito    600 Hokkaido
5   e    Yamada    700 Hokkaido
6   f  Yamamoto    700 Hokkaido
7   g Yamaguchi    600  Okinawa
8   h   Taguchi    500  Okinawa
9   I   Iwamoto    300    Tokyo
10  j    Takada    500    Tokyo
11  k      Ueda    600  Okinawa

・データフレームやオブジェクトの構造を確認したい場合、attributes関数が便利。

> attributes(df)
$names
[1] "ID"       "Name"     "Nenshu"   "Shusshin"

$class
[1] "data.frame"

$row.names
 [1]  1  2  3  4  5  6  7  8  9 10 11

 

・データフレームの変数を確認したい場合、str関数やtable関数を使う。table関数では、クロス集計っぽいこともできる。

> str(df)
'data.frame':    11 obs. of  4 variables:
 $ ID      : chr  "a" "b" "c" "d" ...
 $ Name    : chr  "Tanaka" "Sato" "Suzuki" "Saito" ...
 $ Nenshu  : int  300 400 500 600 700 700 600 500 300 500 ...
 $ Shusshin: chr  "Tokyo" "Tokyo" "Hokkaido" "Hokkaido" ...

 

> table(df$Nenshu)

300 400 500 600 700 
  2   1   3   3   2 

 

> table(df$Nenshu,df$Shusshin)
     
      Hokkaido Okinawa Tokyo
  300        0       0     2
  400        0       0     1
  500        1       1     1
  600        1       2     0
  700        2       0     0

・割合を調べたければ、prop.table関数を使う。

> prop.table(table(df$Nenshu,df$Shusshin))

        Hokkaido    Okinawa      Tokyo
  300 0.00000000 0.00000000 0.18181818
  400 0.00000000 0.00000000 0.09090909
  500 0.09090909 0.09090909 0.09090909
  600 0.09090909 0.18181818 0.00000000
  700 0.18181818 0.00000000 0.00000000

・何かの変数に含まれるUniqueな値を調べたければ、Unique関数を使う。

> unique(df$Shusshin)
[1] "Tokyo"    "Hokkaido" "Okinawa" 

 

・データフレームに変数を追加したい場合は、df$変数名<-で代入できる。

> df$Shincho<-c(123,134,145,156,167,178,190,132,143,154,165)
> df
   ID      Name Nenshu Shusshin Shincho
1   a    Tanaka    300    Tokyo     123
2   b      Sato    400    Tokyo     134
3   c    Suzuki    500 Hokkaido     145
4   d     Saito    600 Hokkaido     156
5   e    Yamada    700 Hokkaido     167
6   f  Yamamoto    700 Hokkaido     178
7   g Yamaguchi    600  Okinawa     190
8   h   Taguchi    500  Okinawa     132
9   I   Iwamoto    300    Tokyo     143
10  j    Takada    500    Tokyo     154
11  k      Ueda    600  Okinawa     165

 

・条件でデータを抜き出したい場合、以下のようにTURE/FALSEで抜き出せる。

> df$Nenshu>500
 [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE
[10] FALSE  TRUE

> df[df$Nenshu>500,]
   ID      Name Nenshu Shusshin Shincho
4   d     Saito    600 Hokkaido     156
5   e    Yamada    700 Hokkaido     167
6   f  Yamamoto    700 Hokkaido     178
7   g Yamaguchi    600  Okinawa     190
11  k      Ueda    600  Okinawa     165

 

・Bool型は!でひっくり返すことができるので、特定の条件に合わないものを抽出することもできる。これを使って、特定の列を削除すると以下のような感じ。"Shincho"列が消えた。

> df<-df[!colnames(df)=="Shincho"]
> df
   ID      Name Nenshu Shusshin
1   a    Tanaka    300    Tokyo
2   b      Sato    400    Tokyo
3   c    Suzuki    500 Hokkaido
4   d     Saito    600 Hokkaido
5   e    Yamada    700 Hokkaido
6   f  Yamamoto    700 Hokkaido
7   g Yamaguchi    600  Okinawa
8   h   Taguchi    500  Okinawa
9   I   Iwamoto    300    Tokyo
10  j    Takada    500    Tokyo
11  k      Ueda    600  Okinawa

 

・どれかの列を基準に表を並び替えたいときは、order関数で行番号の順位をつけてデータをぬきだすような処理をする。例えば年収で昇順に並べると以下のような感じ。降順に並べたければ、引数decreasingにTRUEを与えればいけるっぽい。

> df[order(df$Nenshu),]
   ID      Name Nenshu Shusshin
1   a    Tanaka    300    Tokyo
9   I   Iwamoto    300    Tokyo
2   b      Sato    400    Tokyo
3   c    Suzuki    500 Hokkaido
8   h   Taguchi    500  Okinawa
10  j    Takada    500    Tokyo
4   d     Saito    600 Hokkaido
7   g Yamaguchi    600  Okinawa
11  k      Ueda    600  Okinawa
5   e    Yamada    700 Hokkaido
6   f  Yamamoto    700 Hokkaido

 

おわり。

 

 

 

【R】Rの使い方メモ①

・お題:データ分析をするのにRを使いたいのだけれど、私の頭はザルなので、全然頭に残らない。そこで、使い方を簡単にメモしておきたい。

 

・Rの導入

基本的なことは以下のサイトに網羅されている。感謝。RとRStudioを放り込んで、環境を構築した。

htsuda.net

・カレントディレクトリの設定

Sessionから順番に辿ることができる。もしくは、setwd()で指定しても良い。

・変数に代入するときは、<-を使う。例えば、aに1を代入したいときは、a<-1と記述する。実行するときはenterを押せば良い。変数は右のウィンドウに出てくる。ちなみに、Rでは変数をオブジェクトと呼ぶらしい。

・コンソールにはつらつらとコードやアラートが出てくるけれど、見苦しくなることもある。そんな時は、ctrl + lするとコンソールが綺麗になる。コンソールは綺麗になるけれど、オブジェクトはちゃんと残っている。

・ちなみに、代入する際に<-ではなくて=を使用することもできる。bに2を代入したければ、b=2と記述しても良い。

・どんなオブジェクトがあるか一覧で確認したければ、ls()する。ちなみに、objects()という関数でも同じ結果を呼び出すことができる。

・関数やオブジェクトなどを呼び出すときは、最初の数文字を入力してtabキーを押すと補完された候補がでてくる。

・特定のオブジェクトを削除したいときは、rm("変数名")で削除できる。

・すべてのオブジェクトを削除したければ、rm(list=ls())でいける。

・数列を作りたければ、整数:整数でできる。

・これだとオブジェクトになっていないので、ベクトルにする。c(**,**,**,**)でベクトルを作ることができる。

・ベクトル内は同じデータ型で、番号を指定して切り出すことができる。ちなみに、Pythonは0から始まるが、Rは1から始まる。

・データを取り出すときに、ベクトルで要素の場所を複数指定することができる。ちなみに、1:5のように指定すれば、1番目から5番目までをとって来ることもできる。

・ベクトルの要素数を知りたければlength()関数を使う。ちなみに、要素の計算とかも簡単にできる。

・データフレームを作りたければ、data.frame関数を使う。

・データフレームの頭の方をとってきたければhead、お尻の方をとってきたければtailを使う。引数で取ってきたい行数を指定できる。

・行名はrownames、列名はcolnames、行数はnrow、列数はncolでとってこれる。

・特定の列をとってきたければ、df$"列名"などで取ってこれる。$を入力した時点で、列名が入力候補に出てきてくれて便利。Pythonのように["列名"]で指定することもできる。

csvを読み込むときは、read.csvを使う。カレントディレクトリ直下にtest.csvを置いたので、ファイル名だけで読み込める。df2として読み込みたいなら、df2<-とかを前にくっつける。タブ区切りファイルを読み込む際はsep="\t"、カンマ区切りを読み込む際はsep=","、headerを列名として認識する/しない場合はheader=TRUE/FALSEにする。

・read.table(file.choose())とすると、ファイルを選択するためのウィンドウが開く。「キャンセル」を選択するとエラーになる。

 

 

おわり。

【Python】分類問題で遊んでみたい。

・お題:機械学習というやつで遊んでみたくて、画像に写っているものが何か分類する問題をやってみようと思った。有名な問題で、手書きの数字画像がなんの数字か判別するモデルを作るやつがあるらしい。やってみたい。

 

・とりあえず、データをロードしてみる。

from sklearn.datasets import load_digits
Data = load_digits(n_class=10)

・Dataの中身が何か分からないので、確認してみる。まず、画像データを確認する。

Data.imagesで以下が返ってくる。

array([[[ 0.,  0.,  5., ...,  1.,  0.,  0.],
        [ 0.,  0., 13., ..., 15.,  5.,  0.],
        [ 0.,  3., 15., ..., 11.,  8.,  0.],
        ...,

・画像データ…なのか?最初の画像データを抜き出してみる。

Data.images[0]で以下が返ってくる。

array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],
       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],
       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],
       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],
       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],
       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],
       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],
       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.]])

・画像のイメージが掴めないので、pandasのdataframeに取り込んで、Heatmapにしてみる。

import pandas as pd
df0=pd.DataFrame(Data.images[0])

df0.style.background_gradient(cmap="Greys" )

・おお。これはたぶんゼロだ。数値の大きさがそのまま濃淡を表しているらしい。pandasのdataframeだとまだ表っぽいので、画像っぽく表示したい。ちょっとやってみる。

import matplotlib.pyplot as plt
plt.imshow(Data.images[0], cmap=plt.cm.binary)

・次に、正解のラベルを確認する。

Data.targetで、以下が返ってくる。

array([0, 1, 2, ..., 8, 9, 8])

なるほど正解ラベルのリストっぽい。len(Data.target)で1797が返ってくる。

機械学習では、データセットすべてでモデルを作成するのではなく、データセットを学習用とテスト用に分けて、学習用データでモデル構築、テスト用データでモデルの性能評価をするらしい。とりあえずデータをカチ割る。

X = Data.images#Xは説明変数。画像データに相当するが、今回は数値のリストのリスト。
y = Data.target #yは目的変数。正解ラベルの数値のリスト。

import numpy as np

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

・今回は、画像データの色の濃淡を表す数値を使って、正解ラベルを予測することにする。画像データの色の濃淡が、数値のリストのリストのままだと扱いにくいので、数値のリストにする。FAXのようなイメージ。

X_train_flat=[n.flatten() for n in X_train]
X_test_flat=[n.flatten() for n in X_test]

・これで、X_train_flatは数値のリストになる。

[array([ 0.,  0.,  0.,  8., 10., 14.,  3.,  0.,  0.,  1., 13., 13.,  9.,
        12.,  8.,  0.,  0.,  6., 16.,  8.,  8., 16.,  4.,  0.,  0.,  5.,
        16., 16., 16.,  9.,  0.,  0.,  0.,  0.,  5.,  8., 14., 12.,  0.,
         0.,  0.,  0.,  0.,  3., 16.,  5.,  0.,  0.,  0.,  0.,  0., 15.,
         8.,  0.,  0.,  0.,  0.,  0.,  1., 12.,  2.,  0.,  0.,  0.]),

......

・今回は、random forestを使って分類モデルを作成する。

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(max_depth=10)
rf.fit(X_train_flat, y_train)

・accuracyを見てみる。
rf.score(X_test_flat, y_test)で0.975925925925926が返ってきた。なんだか良さそう。

・ここで気になるのは、どういう画像で間違えたのか、だと思う。confusion matrixを描いても良いけれど、今回は間違ったものを抽出した方が、どんな画像が間違えやすいか分かりやすい気がする。

・せっかくなので、probabilityも算出して表にしてみる。

import pandas as pd
df = pd.DataFrame(rf.predict_proba(X_test_flat))

df["pred_test"] = pred_test

df["y_test"] = y_test

df_mistake = df[[not n for n in  df["pred_test"] == df["y_test"]]]

・これで、df_mistakeは以下になる。例えば、index 117は、0か2かで悩んで0と予測したらしい。答えが2だったので、惜しかったかもしれない…?よく見ると、1番probabirityが高いクラスはもちろん間違っているが、2番目に高いクラスは結構正解になっている。

・せっかくなので、どんな画像だったか確認してみる。

for n in range(len(df_mistake)):
    plt.figure(figsize=(1,1))
    plt.imshow(X_test[df_mistake.index[n]], cmap=plt.cm.binary)

……

・納得いかない間違い方をしている画像もあるし、あぁこれは確かに紛らわしい(というか人間でも普通に読み間違えるだろう)という画像もあった。Random Forest以外の手法などでやってみても面白いと思うし、ハイパーパラメータをもっとチューニングしても良いと思う。ちょっと楽しい。

 

おわり。