52998


Rのバグのように感じたので、質問です。

このようなデータベースがあったとします。

[code]

    sex    <- c("F","F","F","M","M")
    height <- c(159,163,178,172,165)
    weight <- c(61,65,82,67,74)
    sports <- c("1","2","0",NA,"2")
    goal    <- c("1","1","0","0","0")
    data_set <- data.frame(SEX=sex, HEIGHT=height, WEIGHT=weight,SPORTS=sports,GOAL=goal)
    data_set
    
[/code]

\- SPORTS=2:毎週かなり運動している,1:少しは運動している,0:運動習慣がない,NA:無回答  
\- GOAL=1:goalした,0:goalできなかった

とします。

ifelse()を使って、「スポーツ習慣がある人」をまとめようとする（二値変数のfactorに）と、

[code]

    data_set$SPORTS <- as.factor(ifelse(data_set$SPORTS=="2","1",data_set$SPORTS))
    data_set$SPORTS
    
[/code]

とすると、下のように順序だけでなくバラバラな数値があてがわれてしまっていました。

ID before after  
1 1 2  
2 2 1  
3 0 1  
4  
5 2 1

となり、「かなり運動している人」がなぜか、「運動習慣がない」という分類になってしまいました。  
しばらく気づかず、解析結果も大きく変わりました。  
結構やってしまいがちな気がしました。

これはどのような理由で起こるのでしょうか？  
as.factor()のlabel,level問題と同じような理由なのでしょうか？  
こんな事が他にも起こっていたらと思うとゾッとしますが、使い慣れておられる方たちはこういったバグを避けるために何かされているのでしょうか？

ちなみに構造を見ると、  
`str(data_set$SPORTS)`  
Factor w/ 3 levels "0","1","2": 2 3 1 NA 3  
`str(ifelse(data_set$SPORTS=="2","1",data_set$SPORTS))`  
chr [1:5] "2" "1" "1" NA "1"  
`str(as.factor(ifelse(data_set$SPORTS=="2","1",data_set$SPORTS)))`  
Factor w/ 2 levels "1","2": 2 1 1 NA 1  
となります。  
ifelseが"1"をlevel=1と勘違いしているような印象でしたが、よくわかりませんでした。


CC BY-SA 4.0
2018-12-29T06:53:16.320
51597
2019-02-24T15:24:51.153
2018-12-29T08:26:08.517
31615
31615
question
r
R ifelse()のバグ？


あなたは望みの振る舞いを達成するために `factor`を`character`に変換する必要があります。 下記を参照してください：

[code]

    sex <- c ("F", "F", "F", "M", "M")
    height <- c (159, 163, 178, 172, 165)
    weight <- c (61, 65, 82, 67, 74)
    sports <- c ("1", "2", "0", NA, "2")
    goal <- c ("1", "1", "0", "0", "0")
    data_set <- data.frame(SEX = sex, HEIGHT = height, WEIGHT = weight, SPORTS = sports, GOAL = goal)
    
    data_set$SPORTS_before <- data_set$SPORTS
    # by OP
    data_set$SPORTS_OP <- as.factor (ifelse (data_set $ SPORTS == "2", "1", data_set $ SPORTS))
    
    # correct with as.character
    data_set$SPORTS_after <- as.factor(ifelse(as.character(data_set$SPORTS) == "2", "1", as.character(data_set $ SPORTS)))
    
    data_set[, c("SPORTS_before", "SPORTS_after")]
    
[/code]

アウトプット:

[code]

      SPORTS_before SPORTS_after
    1             1            1
    2             2            1
    3             0            0
    4          <NA>         <NA>
    5             2            1
    
[/code]

そうです、それが起こる理由は、`ifelse`の`factor`から`integer`への暗黙の変換です。 から明らかなように：

`Factor w/ 3 levels "0","1","2": 2 3 1 NA 3`

したがって、 `"0"`、 `"1"`、 `"2"`は、 `factor`、 `integer`値、 `1`、 `2`、 `3`に対応します。
それからこれらの `integer`値は`character`に変換されるので、あなたはあなたが気付いた効果を得ることができます。


CC BY-SA 4.0
2019-02-24T15:24:51.153
52998
2019-02-24T15:24:51.153
32306
51597
answer