0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

applyとsapplyの挙動の違いについて

Last updated at Posted at 2021-02-12

はじめに

Rでデータフレームへいろいろと操作するとき、applysapplyの動作の違いでちょっとハマってしまったので、備忘録として記事を残しておく。

saplly,apply関数とis.characterでの文字列の判定

文字列と数字の混ざったデータから、数字データのみを取り出したかった。ので、以下のようなデータフレームを準備する。

コード
a <- c(1, 3, 7)
b <- c("test1", "test2", "test3")
c <- c(0.8, 0.6, 0.4)

x <- data.frame(a, b, c)
x
出力
  a     b   c
1 1 test1 0.8
2 3 test2 0.6
3 7 test3 0.4

ここから、b列を文字判定してTRUE, FALSEのベクトルをつくり、再度データフレームを再構築すれば、実装できそう。なのでapply関数を使いis.characterを列に適応する。

コード
apply(x, 2, is.character)
出力
   a    b    c 
TRUE TRUE TRUE 

なぜか、数字のみが入っているa, c も文字列判定されてしまった。ここで、ならばsapplyではどうなるか疑問が生じたので試してみる。

コード
sapply(x, is.character)
出力
    a     b     c 
FALSE  TRUE FALSE 

こんどは上手くいった!ので、文字列以外の要素でデータフレームを再構成すると、

コード
y <- x[, !sapply(x, is.character)]
y
出力
  a   c
1 1 0.8
2 3 0.6
3 7 0.4

となり、これで文字列を除外した数値のみのデータが作れた。

apply関数が目的の通り動作しなかった理由

ここでapply関数のヘルプを見てみると(?applyを実行すると)、

If X is not an array but an object of a class with a non-null dim value (such as a data frame), apply attempts to coerce it to an array via as.matrix if it is two-dimensional (e.g., a data frame) or via as.array.

とある。つまりデータフレームなどはas.matrixを通して操作することになる、と。では、as.matrixはと言うと、

The method for data.tables will return a character matrix if there are only atomic columns and any non-(numeric/logical/complex) column, applying as.vector to factors and format to other non-character columns. Otherwise, the usual coercion hierarchy (logical < integer < double < complex) will be used, e.g., all-logical data frames will be coerced to a logical matrix, mixed logical-integer will give an integer matrix, etc.

とある。英語が苦手なのできちんと読み解けているか不安だが、非(数値、論理、複素数)型が含まれていると、「文字列」で値を返す仕様らしい。as.matrixの出力を見てみると、

コード
as.matrix(x)
出力
     a   b       c    
[1,] "1" "test1" "0.8"
[2,] "3" "test2" "0.6"
[3,] "7" "test3" "0.4"

となり、確かに全部文字列になってしまっている。もし、b列が無いデータ(整数と少数のみのデータ)の場合は、

コード
tmp <- data.frame(a,c)
tmp
出力
  a   c
1 1 0.8
2 3 0.6
3 7 0.4
コード
as.matrix(tmp)
出力
     a   c
[1,] 1 0.8
[2,] 3 0.6
[3,] 7 0.4
コード
apply(tmp, 2, is.character)
出力
    a     c 
FALSE FALSE 

となり、全て想定通りの挙動を示した。

おわりに

sapplyは値をリストとして扱ってくれるのでこの問題が起きない、と思われる。

sapplyの詳しい説明はヘルプを見てもよく分からなかったので、もし補足等あればコメント頂けますと幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?