应用,数据帧和布尔值不能一起使用?

时间:2018-04-18 20:19:11

标签: r

在下文中,逻辑运算符似乎无法正常工作。

a = c(TRUE, FALSE, TRUE, FALSE, TRUE, TRUE)
b = c('a', 'b', 'c', 'de', 'f', 'g')
c = c(1, 2, 3, 4, 5, 6)
d = c(0, 0, 0, 0, 0, 1)

wtf = data.frame(a, b, c, d)
wtf$huh = apply(wtf, 1, function(row) {
    if (row['a'] == T) { return('we win') }
    if (row['c'] < 5) { return('hooray') }
    if (row['d'] == 1) { return('a thing') }
    return('huh?')
})

产:

> wtf
      a  b c d     huh
1  TRUE  a 1 0  hooray
2 FALSE  b 2 0  hooray
3  TRUE  c 3 0  hooray
4 FALSE de 4 0  hooray
5  TRUE  f 5 0    huh?
6  TRUE  g 6 1 a thing

天真地想要在第1,3,5和6行中,会有we win

有人可以向我解释(1)为什么会这样做,(2)如何修复它以使其不会发生,(3)为什么我的所有逻辑列似乎都被改为字符,以及(4)如何将函数类型安全地应用于数据框中的行?

3 个答案:

答案 0 :(得分:7)

为什么会这样?因为apply是为矩阵而制作的。当你给它一个数据框时,发生的第一件事是它被转换为矩阵:

m = as.matrix(wtf)
m 
#      a       b    huh    huh1    
# [1,] " TRUE" "a"  "huh?" "hooray"
# [2,] "FALSE" "b"  "huh?" "huh?"  
# [3,] " TRUE" "c"  "huh?" "hooray"
# [4,] "FALSE" "de" "huh?" "huh?"  
# [5,] " TRUE" "f"  "huh?" "hooray"
# [6,] " TRUE" "g"  "huh?" "hooray"

当发生这种情况时,您的不同数据类型会丢失,而您的数据框样式索引不再起作用:

m['a']
# [1] NA

解决方案?使用简单的for循环:

wtf$huh1 = NA
for (i in 1:nrow(wtf)) {
        wtf$huh1[i] = if(wtf[i, 'a']) "hooray" else "huh?"
}

如果你有一个函数foo那么

wtf$huh2 = NA
for (i in 1:nrow(wtf)) {
        wtf$huh1[i] = foo(wtf[i, 'a'])
}

没有矢量化的函数可以进行矢量化以避免需要循环:

foov = Vectorize(foo)
# then you can
wtf$huh4 = foov(wtf$a)

答案 1 :(得分:1)

解决此问题的最简单方法可能是使用ifelse进行矢量化,因此您不需要处理循环,或apply

myfunc <- function(row) {
     ifelse (row['a'] == T,'hooray','huh?')
 }

wtf$huh <- myfunc(wtf)

      a  b      a
1  TRUE  a hooray
2 FALSE  b   huh?
3  TRUE  c hooray
4 FALSE de   huh?
5  TRUE  f hooray
6  TRUE  g hooray

答案 2 :(得分:1)

data.frame的一个优点是它们可以包含不同类型变量的变量。

    lapply(wtf, typeof)
    $a
    [1] "logical"

    $b
    [1] "factor"

    $huh
    [1] "character"

正如Gregor所说,apply需要一个矩阵,如果可能的话,会将你给它的对象转换成一个。但是矩阵不能包含多个变量类型,因此as.matrix将寻找可以表示数据的最小公分母,在本例中为字符。

    typeof(as.matrix(wtf))    
    [1] "character"

    class(as.matrix(wtf))    
    [1] "matrix"