【问题标题】:Inconsistent results in apply申请结果不一致
【发布时间】:2019-04-03 17:49:07
【问题描述】:

这基本上是here 提出的问题(不是我提出的),但我已经简化了示例,我根本无法弄清楚发生了什么,所以我决定以某种方式再次提出它这可能会得到更多的回应。

取数据dd:

dd <- structure(list(first = c("118751", "55627", NA), one = c(41006L, 
119098L, 109437L), two = c(118751L, 109016L, 109831L), three = c(122631L, 
104639L, 120634L), four = c(38017L, 118950L, 105440L), five = c(114826L, 
122047L, 124347L), six = c(109438L, 55627L, 118679L), seven = c(27094L, 
107044L, 122161L), eight = c(112473L, 116909L, 124363L), nine = c(120586L, 
114711L, 120509L)), row.names = c(NA, 3L), class = "data.frame")

dd
   first    one    two  three   four   five    six  seven  eight   nine
1 118751  41006 118751 122631  38017 114826 109438  27094 112473 120586
2  55627 119098 109016 104639 118950 122047  55627 107044 116909 114711
3   <NA> 109437 109831 120634 105440 124347 118679 122161 124363 120509

现在,我们要使用apply 来查找first 列中的数字等于six 列中的数字(这是数据框中的第七列)的行:

apply(dd,1,function(x) as.integer(x["first"])==x[7])

    1     2     3 
FALSE FALSE    NA 

这个结果显然是错误的 - 2 应该产生一个 TRUE。奇怪的是,如果我只在第二行运行相同的东西,我会得到正确的答案:

apply(dd[2,],1,function(x) as.integer(x["first"])==x[7])

   2 
TRUE 

我还尝试了其他子集 - 1:2、2:3 甚至 c(1,3)。后者给了我预期的结果,而前两个一直坚持第 2 行为 FALSE。

如果我删除apply,我会得到正确的响应(不管子集):

as.integer(dd$first)==dd$six
[1] FALSE  TRUE    NA

这到底是怎么回事?

【问题讨论】:

  • 看看apply(dd, 1, function(x) x)——apply 是为矩阵设计的,它会以你意想不到的方式将你的数字填充成字符串。

标签: r apply


【解决方案1】:

问题在于您的数据类型。您的第一列是character,其余列是整数。您尝试在apply 中使用as.integer() 对此进行更正,但为时已晚。 apply 适用于矩阵,而不是数据帧。当你给它一个数据框时,它会立即转换为一个矩阵。矩阵不能有不同的列类,并且(通常)character 不能转换为numeric,因此您的所有数据都转换为character

这是转换的窗口:

apply(dd, 1, print)
#       1        2        3       
# first "118751" "55627"  NA      
# one   " 41006" "119098" "109437"
# two   "118751" "109016" "109831"
# three "122631" "104639" "120634"
# four  " 38017" "118950" "105440"
# five  "114826" "122047" "124347"
# six   "109438" " 55627" "118679"
# seven " 27094" "107044" "122161"
# eight "112473" "116909" "124363"
# nine  "120586" "114711" "120509"

不幸的是,你可以看到空格也被添加了,这使得等式不成立。

相反,首先将您的列转换为正确的类型。或者,更好的是,根本不用apply

# convert
dd[, "first"] = as.integer(dd[, "first"])

# apply now works
apply(dd, 1, function(x) x["first"] == x[7])
#     1     2     3 
# FALSE  TRUE    NA 

# but isn't this easier?
dd[, "first"] == dd[, "six"]
# [1] FALSE  TRUE    NA

【讨论】:

  • 是的,我已经在我的问题中指出,放弃应用可以使其工作。最初的原始问题更复杂,需要apply(据我所知)。但这也应该能帮助我解决这个问题。谢谢!
【解决方案2】:

x[7] 包裹在as.integer() 中可以解决您的问题

apply(dd,1,function(x) as.integer(x["first"])==as.integer(x[7]))

因为如果您运行以下代码,您可以看到 as.integer(x["first"])x[7] 正在返回不可比较的不同 class 类型。

apply(dd,1,function(x) return(list(class(as.integer(x["first"])), class(x[7]))))

$`1`
$`1`[[1]]
[1] "integer"

$`1`[[2]]
[1] "character"


$`2`
$`2`[[1]]
[1] "integer"

$`2`[[2]]
[1] "character"


$`3`
$`3`[[1]]
[1] "integer"

$`3`[[2]]
[1] "character"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多