2016-11-12 55 views
1

我继承了一些遗留的R代码来处理该代码,该代码基于同一行中的某个其他列中的值重新编码列中的某些值这被误认为是时,在现实中,这些值实际上是(字符串转换为)的因素,像这样一个布尔值:R:意外地使用因子列对数据框进行子集化,就好像它是逻辑的一样

df <- data.frame(value = c(1, 2, 3, 4, 5, 6), 
       reversed = c("true", "false", 
           "true", "true", 
           "false", "false")) 

str(df) 
#> 'data.frame': 6 obs. of 2 variables: 
#> $ value : num 1 2 3 4 5 6 
#> $ reversed: Factor w/ 2 levels "false","true": 2 1 2 2 1 1 

df$recoded_value <- df$value 
df$recoded_value[df$reversed] <- 7 - df$recoded_value[df$reversed] 

如果检查的结果,这将产生意外的结果。 df[2, "recoded_value"]是5,但意图是它是2.此外,df[3, "recoded_value"]是3,但意图是它为4.

我想了解这里发生了什么。我的第一个假设是R将一个因子水平作为TRUE,另一个作为FALSE。但是,这显然并非如此,因为相同的因素水平被同等对待:

df[c(1,3), ] 
#> value reversed recoded_value 
#> 1  1  true    6 
#> 3  3  true    3 

df[c(2,5), ] 
#> value reversed recoded_value 
#> 2  2 false    5 
#> 5  5 false    5 

这到底是怎么回事?

澄清:我对问题的解决方案不感兴趣。我知道如何修复代码以产生预期的结果。我想了解:

  1. 为什么此代码可以工作?你如何基于因子列进行子集划分?什么是`[`甚至允许这样做?
  2. 为什么相同价值的东西(,即,相同水平的因素)被区别对待?

回答

1

由于它是在后提到的,reversedfactor而不是logical矢量。在RTRUE/FALSE值逻辑,所以转换为logical矢量

df$reversed <- df$reversed=="true" 

至于为什么我们会有意想不到的输出(来自OP的代码),

df$reversed 
#[1] true false true true false false 
#Levels: false true 

levels都按字母顺序并且factor的存储模式是integer

as.integer(df$reversed) 
#[1] 2 1 2 2 1 1 

所以,当我们子集“recoded_value”使用“逆转”,它将子集基础上的数字指标

df$recoded_value[df$reversed] 
#[1] 2 1 2 2 1 1 

即在输出的第一个值是“recoded_value”和第二一号的第二观察观察等,而是如果我们用正确的逻辑索引

df$recoded_value[df$reversed=="true"] 
#[1] 1 3 4 

让我们来看看如何将与改变“逆转”的行为

df$reversed <- df$reversed=="true" 
df$recoded_value[df$reversed] <- 7 - df$recoded_value[df$reversed] 
df[c(1,3), ] 
# value reversed recoded_value 
#1  1  TRUE    6 
#3  3  TRUE    4 
df[c(2,5),] 
# value reversed recoded_value 
#2  2 FALSE    2 
#5  5 FALSE    5 
+1

感谢您的回答!不知道为什么我以前没有意识到这一点。我认为在构建最简单的例子时我选择了糟糕的数字;我不应该选择与行号相同的值。 ':-p'无论如何,谢谢。 +1 –