假设我有一个数据框:
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
的函数,它没有上述行为?
答案 0 :(得分:3)
当您致电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
答案 1 :(得分:1)
apply
无法直接使用data.frames;它适用于矩阵和矩阵,所有元素必须是相同的原子类型。如果您传入data.frame,apply()
会将其强制转换为矩阵。由于字符值无法以更“简单”的数据类型存储,因此所有内容都会转换为字符值。
通常,您没有考虑过一次将函数应用于data.frame的行。大多数情况下,您可以使用data.frame列中的基本向量函数来完成您想要完成的任务。如果你想要
ifelse(apply(mydf, 1, '[', 3), 1, 2)
尝试
ifelse(mydf[, 3], 1, 2)
代替