Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apply、dataframes和booleans don';我们不能一起工作吗?_R - Fatal编程技术网

Apply、dataframes和booleans don';我们不能一起工作吗?

Apply、dataframes和booleans don';我们不能一起工作吗?,r,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) { retu

在下面的示例中,逻辑运算符似乎无法正常工作

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?')
})
我们天真地期望在第1、3、5和6行中会有
我们赢了


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

为什么会发生这种情况?因为is
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)

解决这个问题最简单的方法可能是使用向量化的
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

myfuncdata.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"

在寻求帮助时,您应该包括一个简单的示例输入和所需的输出,可用于测试和验证可能的解决方案。对data.frames使用
apply
不是一个好主意,因为它首先强制使用一个可以更改所有数据类型的矩阵。同意@MrFlick的观点,问题几乎可以肯定是使用
apply
。那么如何解决这一问题,使其不会发生呢?purrr中有一些精巧的工具可以对数据帧进行逐行操作,但坦率地说,一个简单的for循环将是一个很好的起点。要清楚,
apply
工作正常,只是它的正确行为令人困惑<代码>应用
严格地将数据帧强制为矩阵。矩阵只能包含一种数据类型。因此,通常所有内容都会变成字符(或它可以强制执行的最常见的内容)。有没有办法通过提供的函数实现这一点?那么它是什么?细节可能取决于函数,但类似于我刚才在编辑中添加的内容。如果函数将该行作为其参数会怎么样?@ifly6然后将该行作为参数。您不知道如何为数据帧编制索引吗
foo(wtf[i,])
(在我的for循环示例中)。但这是一个糟糕的函数,它只需要一行数据帧——数据帧并不意味着一次只能处理一行。
    typeof(as.matrix(wtf))    
    [1] "character"

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