2016-09-06 5 views
7

このコードはなぜですか:as.factor(c("\U201C", '"3', "1", "2", "\U00B5"))、すべてのオペレーティングシステムで要因レベルの順序が異なりますか? Linuxのユニコード文字列のas.factor()がすべてのオペレーティングシステムで異なる結果を返すのはなぜですか?

:Windowsでは

> as.factor(c("\U201C",'"3', "1", "2","\U00B5")) [1] " "3 1 2 µ Levels: µ " 1 2 "3

:MacのOS上で

> as.factor(c("\U201C",'"3', "1", "2","\U00B5")) [1] " "3 1 2 µ Levels: "3 " µ 1 2

>as.factor(c("\U201C",'"3', "1", "2","\U00B5")) [1] " "3 1 2 µ Levels: "3 " 1 2 µ

私はいくつかの学生がRを提出していましたMardkownの割り当てはas.numeric(as.factor(dat$var))でした。今ではこれがコード化する良い方法ではありませんが、出力の不一致が混乱と時間の無駄につながります。

+0

OS XとFreeBSDは同じですが、どこが違うのかは分かりませんが、OS XとFreeBSDの類似点はどこにあるのでしょうか? – Jemus42

+2

私は答えはありませんが、実際にはRの 'sort'関数に由来している可能性があります。' as.factor'のコードを見ると 'levels < - sort(unique.default(x))'となります。あなたのベクトル上でWindowsとMac OS上で 'sort'を試してみました。 – jav

+3

ロケールのことです。具体的には 'LC_COLLATE'です。 'Sys.setlocale'で設定して何が起きているのかを見ることができます。 – alistaire

答えて

4

これは単なるRではないユニコードです。一般的にsort(* nixコマンドの場合も同様)sortはロケール固有のものです。すべてのマシンでLC_COLLATE(おそらく"C"に設定)をSys.setlocale(@ alistaireのコメントによる)経由で設定してください。 Windows上の私にとって

、(7):

sort(c("Abc", "abc", "_abc", "ABC")) 
[1] "_abc" "abc" "Abc" "ABC" 

Linux上で(Ubuntuの12.04 ...うわー、私はそのマシンをアップグレードする必要がある)のに対し、私はロケール設定

sort(c("Abc", "abc", "_abc", "ABC")) 
[1] "abc" "_abc" "Abc" "ABC" 

を取得

を与える

Sys.setlocale("LC_COLLATE", "C") 

を経由して上記のとおり

sort(c("Abc", "abc", "_abc", "ABC")) 
[1] "ABC" "Abc" "_abc" "abc" 

両方のマシンで同じです。

sortのための* nix manページには、大胆な警告に

*** WARNING *** The locale specified by the environment affects sort 
    order. Set LC_ALL=C to get the traditional sort order that uses native 
    byte values. 

を与える更新: Unicode文字を含むとき、私は、問題を再現するように見えます。問題はsortに戻ります。例の中でベクトルをソートしてみてください。ロケール(LC_COLLATEまたはLC_CTYPE)を"en_AU.UTF-8"に変更することはできません。これは潜在的な解決策です。

+0

ありがとうJono! WindowsとLinuxではLC_COLLATEを "C"に設定し、順序はやや近づいていますが、まだ同じではありません。 – MilesMcBain

+0

まだ一致していないものを表示するためにMREを更新できますか?表現のものかもしれない。 –

+0

更新しました。 Unicodeはうまくいきませんし、UTF-8に変更することで潜在的に解決されますが、強制する方法はわかりません。 –

2

'factor'構造体は文字値に変換することを前提としているため、フォントやその他のコードでエンコードする必要があります。デフォルトはOS固有です。レキシカルソート順はロケールに従います。この質問の爪にローランドの前に答え@便利な限り、ロケールの問題ではなく、エンコーディングの問題に

Is the default ("automatic") ordering for factors a part of the R specification? Alphabetical? Same on all platforms?

0

私は、ロケール設定を変更しようとしたが、この問題を解決することができませんしています。しかし、この問題をsort関数に戻すことができることを考えれば、factor関数とas.factor関数をsort関数なしで再定義することが考えられます。

as.factor2 <- function(x){ 
    if (is.factor(x)) 
    x 
    else if (!is.object(x) && is.integer(x)) { 
    levels <- unique.default(x) # Removed sort() 
    f <- match(x, levels) 
    levels(f) <- as.character(levels) 
    class(f) <- "factor" 
    f 
    } 
    else factor2(x) 
} 

factor2 <- function (x = character(), levels, labels = levels, exclude = NA, 
      ordered = is.ordered(x), nmax = NA) 
{ 
    if (is.null(x)) 
    x <- character() 
    nx <- names(x) 
    if (missing(levels)) { 
    y <- unique(x, nmax = nmax) 
    ind <- 1:length(y) # Changed from sort.list(y) 
    y <- as.character(y) 
    levels <- unique(y[ind]) 
    } 
    force(ordered) 
    exclude <- as.vector(exclude, typeof(x)) 
    x <- as.character(x) 
    levels <- levels[is.na(match(levels, exclude))] 
    f <- match(x, levels) 
    if (!is.null(nx)) 
    names(f) <- nx 
    nl <- length(labels) 
    nL <- length(levels) 
    if (!any(nl == c(1L, nL))) 
    stop(gettextf("invalid 'labels'; length %d should be 1 or %d", 
        nl, nL), domain = NA) 
    levels(f) <- if (nl == nL) 
    as.character(labels) 
    else paste0(labels, seq_along(levels)) 
    class(f) <- c(if (ordered) "ordered", "factor") 
    f 
} 

次のように現在as.factor2を呼び出すことができます。

as.factor2(c("\U201C",'"3', "1", "2","\U00B5")) 
# [1] “ "3 1 2 µ 
# Levels: "3 “ 1 2 µ 

私はこれがあなたの問題を解決することを言わないだろう。これはもっと回避策です。特にこれには学生を教えることが必要なので、ベースのR関数を再作成したくないです。うまくいけば、他の誰かがより簡単な解決法を提供することができます。

+0

これは予期しない結果を招く可能性があります。いくつかの関数は、レベルが順序付けされていると仮定します。 – Roland

+0

これは常に、発生した順序で要素を返しますか?それはそれを行うためのプラットフォームにとらわれない最善の方法のようです。ベースを書き直すのは良いことではないと私は同意するが、それはいつも起こる。例えば。 'read_csv()'と 'read.csv()'です。ちなみに、この問題はおそらく 'read.csv()'によって継承されています。たぶん、Hadleyに 'Forcats'に' as_factor() 'を渡すことができます。 – MilesMcBain

+0

私はこの答えのファンではありません。なぜならアルファベット順のソート順が失われる可能性があります。これはUnicode文字列よりもはるかに一般的です。 –

関連する問題