1

data.frameRで有用な非常に予期しない動作は、character列を要素として保持することから発生します。これを考慮しないと、多くの問題が発生します。たとえば、次のコードがあるとします。

foo=data.frame(name=c("c","a"),value=1:2)
#   name val
# 1    c   1
# 2    a   2

bar=matrix(1:6,nrow=3)
rownames(bar)=c("a","b","c")
#   [,1] [,2]
# a    1    4
# b    2    5
# c    3    6

では、何を実行することを期待しますbar[foo$name,]か?通常は、行'c'および'a'を意味するbarに従って名前が付けられた行を返す必要があります。foo$nameしかし、結果は異なります。

bar[foo$name,]
#   [,1] [,2]
# b    2    5
# a    1    4

理由はここにあります:foo$name文字ベクトルではなく、整数ベクトルです。

foo$name
# [1] c a
# Levels: a c

期待される動作を実現するために、手動で文字ベクトルに変換します。

foo$name = as.character(foo$name)
bar[foo$name,]
#   [,1] [,2]
# c    3    6
# a    1    4

しかし、問題は、これを実行するのを簡単に見逃す可能性があり、コードに隠れたバグがあることです。より良い解決策はありますか?

4

2 に答える 2

6

これは機能であり、Rは文書化されているとおりに機能しています。これは、一般的にいくつかの方法で処理できます。

  1. stringsAsFactors = TRUEの呼び出しで引数を使用しますdata.frame()。見る?data.frame
  2. この動作を嫌う場合は、次の方法でオプションをグローバルに設定してください

    options(stringsAsFactors = FALSE)
    
  3. (@JoshuaUlrichがコメントで指摘しているように)3番目のオプションは、文字変数をでラップすることですI(....)。これにより、データフレームコンポーネントに割り当てられているオブジェクトのクラスが変更され、が含まれるようになります"AsIs"。一般に、オブジェクトはクラス(この場合)を継承するため、これは問題にはなりません"character"。以前と同じように機能するはずです。

stringsAsFactors現在実行中のRプロセスのデフォルトが何であるかは、次の方法で確認できます。

> default.stringsAsFactors()
[1] TRUE

data.frame()これはにも影響するため、この問題は範囲よりもわずかに広くなりread.table()ます。その関数では、上記の2つのオプションと同様に、引数を介して変数のすべてのクラスが何であるかをRに伝えることができcolClasses、Rはそれを尊重します。

> tmp <- read.table(text = '"Var1","Var2"
+ "A","B"
+ "C","C"
+ "B","D"', header = TRUE, colClasses = rep("character", 2), sep = ",")
> str(tmp)
'data.frame':   3 obs. of  2 variables:
 $ Var1: chr  "A" "C" "B"
 $ Var2: chr  "B" "C" "D"
于 2012-10-19T21:52:37.993 に答える
0

以下のサンプル データでは、author と title は自動的に factor に変換されます (stringsAsFactors = FALSEデータの作成時に引数を追加しない限り)。デフォルト設定を変更するのを忘れていて、オプションをグローバルに設定したくない場合はどうすればよいでしょうか?

私がどこかで見つけたいくつかのコード(おそらくSO)はsapply()、要因を特定して文字列に変換するために使用します。

dat = data.frame(title = c("title1", "title2", "title3"),
                 author = c("author1", "author2", "author3"),
                 customerID = c(1, 2, 1))
# > str(dat)
# 'data.frame': 3 obs. of  3 variables:
#   $ title     : Factor w/ 3 levels "title1","title2",..: 1 2 3
#   $ author    : Factor w/ 3 levels "author1","author2",..: 1 2 3
#   $ customerID: num  1 2 1

dat[sapply(dat, is.factor)] = lapply(dat[sapply(dat, is.factor)], 
                                 as.character)
# > str(dat)
# 'data.frame':  3 obs. of  3 variables:
#   $ title     : chr  "title1" "title2" "title3"
#   $ author    : chr  "author1" "author2" "author3"
#   $ customerID: num  1 2 1

これは、引数を使用してデータセットを再読み込みするよりも高速であると思いstringsAsFactors = FALSEますが、テストしたことはありません。

于 2012-10-20T04:25:28.850 に答える