hack のためのネタ帳, etc,,,

型判定

is.xxx() 関数で行う。xxx は型名。

型変換

as.xxx() 関数で行う。xxx は型名。

numeric

数値型。
numeric() 関数で任意の個数まとめて作成できる。

character

文字列型。
character() 関数で任意の個数まとめて作成できる。

vector

一次元配列。
c() 関数で作成する。
n 番目の要素へは [n] でアクセスする。n は 1 オリジンのインデックス値(one-based index)。

vector は入れ子にならない。
要素の型はすべて同一となる。

c(11,22,33,44)[1] # 11
c(c(1,2),c(3,4))  # c(1,2,3,4)
c(11,22,33,"44")  # c("11","22","33","44")

list

list() 関数で作成する。
様々なデータ型を内包出来る。
n 番目の要素には [[n]] でアクセスする。
[x] とすると x で指定した要素を抜き出した list が得られる。
list(c(11,22,33),c(44,55,66),c(77,88,99))[[1]]      # c(11,22,33)
list(c(11,22,33),c(44,55,66),c(77,88,99))[1]        # list(c(11,22,33))
list(c(11,22,33),c(44,55,66),c(77,88,99))[c(1,3)]   # list(c(11,22,33), c(77,88,99))
list(c(11,22,33),c(44,55,66),c(77,88,99))[[c(1,3)]] # 33
list(c(11,22,33),c(44,55,66),c(77,88,99))[[1]][3]   # 33

factor

数値インデックス化された文字列というかラベルと言うか。
factor() 関数または ordered() 関数に vector を食わせると重複排除した levels が作成され、内部的には levels のインデックス値への参照になる仕組み。
code=c("Alpha", "Bravo", "Charlie", "Alpha")
phonetic=factor(code)
> phonetic
[1] Alpha   Bravo   Charlie Alpha
Levels: Alpha Bravo Charlie
> levels(phonetic)
[1] "Alpha"   "Bravo"   "Charlie"
> labels(phonetic)
[1] "1" "2" "3"
> as.numeric(phonetic)
[1] 1 2 3 1
> as.character(phonetic)
[1] "Alpha"   "Bravo"   "Charlie" "Alpha"
> phonetic[4]
[1] Alpha
Levels: Alpha Bravo Charlie
> as.numeric(phonetic[4])
[1] 1
> as.character(phonetic[4])
[1] "Alpha"

data.frame

いわゆる行列と言うか、表形式のデータと言うか、フィールド名付きの CSV のようなデータ。
data.frame() 関数で作成する。
与えたパラメータの名前(変数名)がそのままフィールド名(カラム名)になるが、「フィールド名=値」とする事で任意のフィールド名を指定出来る。
vector の内容が文字列の場合、自動的に factor 化される。

m 行 n 列の要素へは [m,n] でアクセスできる。
m, n は行または列の名前でも問題ない。
m, n に vector を与えると複数の行または列が対象となり、省略されるとすべての行またはすべての列が対象となる。
ただし、1列のみ抽出すると data.frame が解除されて vector になる。
これを防ぐには、drop パラメータに FALSE を与える。
フィールド名でアクセスする場合は「$フィールド名」を与えてもよいが、この場合の vector 化の防止方法は良く分からない。

code=c("Alpha", "Bravo", "Charlie")
dec=c(10,11,12)
phonetic = data.frame(code,dec)
phonetic$code  # factor(c("Alpha","Bravo","Charlie"))
phonetic$dec   # c(10,11,12)
nrow(phonetic) # 3
ncol(phonetic) # 2
> phonetic
     code dec
1   Alpha  10
2   Bravo  11
3 Charlie  12
> phonetic[1,]
   code dec
1 Alpha  10
> phonetic[,1] # 1列のみ抽出すると data.frame ではなく vector になる。
[1] Alpha   Bravo   Charlie
Levels: Alpha Bravo Charlie
> phonetic[,1,drop=F] # drop に FALSE を与えると1列のみ抽出時でも data.frame で得られる。
     code
1   Alpha
2   Bravo
3 Charlie
> phonetic[,c(2,1)]
  dec    code
1  10   Alpha
2  11   Bravo
3  12 Charlie
> phonetic[,c("code","dec")]
     code dec
1   Alpha  10
2   Bravo  11
3 Charlie  12

データフレームの合成

データフレームの合成は merge() 関数を使う。
これはフィールド名が同じ列を主キーに見立てて共通の主キーが存在する行を合成する、つまり SQL で言う所の INNER JOIN 句のような結合が出来る。

code=c("Alpha", "Bravo", "Charlie")
dec=c(10,11,12)
phonetic = data.frame(code,dec)

code2=c("Alpha","Delta", "Echo", "Foxtrot")
hex=c("a","d","e","f")
phonetic2=data.frame(code=code2,hex)
> phonetic
     code dec
1   Alpha  10
2   Bravo  11
3 Charlie  12
> phonetic2
     code hex
1   Alpha   a
2   Delta   d
3    Echo   e
4 Foxtrot   f
> merge(phonetic, phonetic2)
   code dec hex
1 Alpha  10   a

全ての行を合成する、つまり SQL で言う所の FULL OUTER JOIN 的に合成するには all=T を与える。
> merge(phonetic, phonetic2, all=T)
     code dec  hex
1   Alpha  10    a
2   Bravo  11 <NA>
3 Charlie  12 <NA>
4   Delta  NA    d
5    Echo  NA    e
6 Foxtrot  NA    f
by を用いると任意のフィールドを主キー扱いすることも出来る。
> merge(phonetic, phonetic2, all=T, by="code")
     code dec  hex
1   Alpha  10    a
2   Bravo  11 <NA>
3 Charlie  12 <NA>
4   Delta  NA    d
5    Echo  NA    e
6 Foxtrot  NA    f
> merge(phonetic, phonetic2, all=T, by.x=c("code","dec"), by.y=c("code","hex"))
     code dec
1   Alpha  10
2   Alpha   a
3   Bravo  11
4 Charlie  12
5   Delta   d
6    Echo   e
7 Foxtrot   f
> merge(phonetic, phonetic2, all=T, by.x=c("dec"), by.y=c("hex"))
  dec  code.x  code.y
1  10   Alpha    <NA>
2  11   Bravo    <NA>
3  12 Charlie    <NA>
4   a    <NA>   Alpha
5   d    <NA>   Delta
6   e    <NA>    Echo
7   f    <NA> Foxtrot

要調査:
LEFT OUTER JOIN、RIGHT OUTER JOIN 相当はどうやれば良いのか?
2019-07-31:
all=T じゃなくて all.x=T とか all.y=T とすれば良いらしい。
> merge(phonetic, phonetic2, all.x=T)
     code dec  hex
1   Alpha  10    a
2   Bravo  11 <NA>
3 Charlie  12 <NA>
> merge(phonetic, phonetic2, all.y=T)
     code dec hex
1   Alpha  10   a
2   Delta  NA   d
3    Echo  NA   e
4 Foxtrot  NA   f


フィールド名が同じデータフレームを cat コマンド的に単純に行方向に繋げる場合は rbind() を用いる。
> rbind(phonetic, phonetic)
     code dec
1   Alpha  10
2   Bravo  11
3 Charlie  12
4   Alpha  10
5   Bravo  11
6 Charlie  12
列方向に繋げる場合は cbind() を用いる。
> cbind(phonetic,phonetic)
     code dec    code dec
1   Alpha  10   Alpha  10
2   Bravo  11   Bravo  11
3 Charlie  12 Charlie  12

データフレームの差分

既成の方法が見つからなかったので以下のような関数を作ってみた。
# 差集合 a - b を得る
group_sub <- function(a,b) {
  c = merge(a,b)
  c = data.frame(c, common=1)
  c = merge(a,c,all=T)
  c[is.na(c$common),names(a),drop=F]
}
> group_sub(phonetic, phonetic2)
     code dec
2   Bravo  11
3 Charlie  12
> group_sub(phonetic2, phonetic)
     code hex
2   Delta   d
3    Echo   e
4 Foxtrot   f
クロス集計形式の度数分布表。
例えば、標準で入ってるデータセットである Titanic がこの形式。
table() 関数でクロス集計して、as.data.frame() 関数でデータフレームに戻せる模様。
ただしデータフレームに戻す際、重複行は行として復元されず度数として Freq 列に集計されるため、rpart で決定木分析するような場合は、Freq 列のカウントを元に、重複行として復元する必要が生じる。

data.frame の所で作った phonetic に対して適用してみるとこんな感じ。
> table(phonetic)
         dec
code      10 11 12
  Alpha    1  0  0
  Bravo    0  1  0
  Charlie  0  0  1
> as.data.frame(table(phonetic))
     code dec Freq
1   Alpha  10    1
2   Bravo  10    0
3 Charlie  10    0
4   Alpha  11    0
5   Bravo  11    1
6 Charlie  11    0
7   Alpha  12    0
8   Bravo  12    0
9 Charlie  12    1
不慣れなので dup 使って無理やり戻すとこんな感じだが、もう少し簡単に書けんものか?
> data.frame(
  code = rep(as.data.frame(table(phonetic))$code, as.data.frame(table(phonetic))$Freq),
  dec  = rep(as.data.frame(table(phonetic))$dec , as.data.frame(table(phonetic))$Freq)
)
     code dec
1   Alpha  10
2   Bravo  11
3 Charlie  12

関連

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

フリーエリア

編集にはIDが必要です