【问题标题】:Why does apply convert logicals in data frames to strings of 5 characters?为什么 apply 将数据帧中的逻辑转换为 5 个字符的字符串?
【发布时间】:2014-11-09 08:08:37
【问题描述】:

假设我有一个数据框:

mydf <- data.frame(colA = c(1,20), colB = c("a", "ab"), colC = c(T, F))

现在假设我想对数据框中的每一行应用一个函数。此函数使用 C 列的布尔值。当使用apply 时,每个非字符串都将转换为列中存在的最大长度的字符串:

> apply(mydf, 1, '[', 3)
[1] " TRUE" "FALSE"

字符串" TRUE" 不再可解释为逻辑。

> ifelse(apply(mydf, 1, '[', 3), 1, 2)
[1] NA  2

我可以用gsub(" ", "", x) 解决这个问题,但我敢打赌有更好的方法。为什么apply 可以直接将逻辑转换为字符串时会有这种行为?是否有没有上述行为的apply-like 函数?

【问题讨论】:

  • 确实如此。有没有这种行为的apply-like 函数?
  • 查看包 plyr,它是基本应用功能的包装器。您可以使用 plyr 方法绕过这些强制影响

标签: r dataframe apply


【解决方案1】:

当您调用apply 时,您的数据框已转换为字符矩阵。出现空格是因为每个元素都转换为列中最宽元素的宽度。

您可以通过 for 循环般的 sapply 调用来做到这一点

> ( s <- sapply(seq(nrow(mydf)), function(i) mydf[i, 3]) )
# [1]  TRUE FALSE
> class(s)
# [1] "logical"

使用apply 的解决方法是

> as.logical(gsub("\\s+", "", apply(mydf, 1, `[`, 3)))
# [1]  TRUE FALSE

但请注意,这些都与

> mydf[,3]
# [1]  TRUE FALSE

【讨论】:

  • 看起来sapply 将是要走的路。我将使用sapply(seq(nrow(mydf)), function(i) myfun(mydf[i, ])),其中myfun 是我的作用于一行的函数。虽然我可能只是编写一个自动执行此操作的函数,因此我可以使用熟悉的apply 语法,而不必每次都写出来。
【解决方案2】:

apply 不能直接与 data.frames 一起使用;它适用于矩阵,并且所有元素都必须是相同的原子类型。如果你传入一个 data.frame,apply() 会将它强制转换为一个矩阵。由于字符值无法存储在更“简单”的数据类型中,因此所有内容都转换为字符值。

通常您不会考虑一次将函数应用于 data.frame 的行。大多数情况下,您想要完成的任务可以使用跨 data.frame 列的基本向量函数来完成。如果你愿意

ifelse(apply(mydf, 1, '[', 3), 1, 2)

试试

ifelse(mydf[, 3], 1, 2)

改为

【讨论】:

    猜你喜欢
    • 2018-01-05
    • 2020-01-14
    • 2014-04-04
    • 1970-01-01
    • 2018-05-12
    • 2017-07-14
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多