Plyr 将 class 从数字更改为字符

Plyr changing class from numeric to character

当我尝试使用 ddply 来总结 data.frame 的某些方面时,如果我只包含产生数字数据的表达式,一切都很好。但是,如果我包含同时产生数字和字符数据的表达式,则所有输出列都会变成字符,这是我绝对没有预料到的,并且真的搞砸了我的下游代码。这是我正在谈论的可重现示例:

library(plyr)
set.seed(1234)
data <- data.frame(x = 1:25,
                   y = c((1:25)*4 + rnorm(100, mean = 0, sd = 50),
                         (1:25)*4 + rnorm(100, mean = 0, sd = 1000)),
                   category = c(rep("stuff with a stronger correlation", 100),
                                rep("stuff with a weaker correlation", 100)))

lmresults <- ddply(data, "category", function(df) c(
      slope = coef(lm(df$y ~ df$x))[2],
      pval = signif(summary(lm(df$y ~ df$x))$coef[2, "Pr(>|t|)"], 2)
))
str(lmresults)

此输出:

'data.frame':   2 obs. of  3 variables:
 $ category  : Factor w/ 2 levels "stuff with a stronger correlation",..: 1 2
 $ slope.df$x: num  4.15 12.31
 $ pval      : num  3.7e-09 3.7e-01    

注意 "slope" 和 "pval" 都是数字。但是,如果我这样做:

lmresults2 <- ddply(data, "category", function(df) c(
      pval = signif(summary(lm(df$y ~ df$x))$coef[2, "Pr(>|t|)"], 2),
      slope = paste("slope =", signif(coef(lm(df$y ~ df$x))[2], 2))
))
str(lmresults2)

输出为:

'data.frame':   2 obs. of  3 variables:
 $ category: Factor w/ 2 levels "stuff with a stronger correlation",..: 1 2
 $ pval    : chr  "3.7e-09" "0.37"
 $ slope   : chr  "slope = 4.1" "slope = 12"

本来以为slope是性格,没想到pval也是性格!

这是 plyr 中的错误吗?是否将输出转换为矩阵,所有数据都必须具有相同的 class?但是如果是这样的话,为什么对象lmresults2的class还是"data.frame"呢?

不,这不是错误。这是因为您在匿名函数中使用了 c() 。根据help(c):

All arguments are coerced to a common type which is the type of the returned value,

...

The output type is determined from the highest type of the components in the hierarchy NULL < raw < logical < integer < double < complex < character < list < expression.

您的第一个匿名函数连接了两个都产生数字的调用,因此没有问题。但是你的第二个匿名函数连接了一个用 signif() 创建的数字和一个由 paste() 创建的字符,因此给出了一个字符结果。

也许您想要 data.frame(pval = ..., slope = ...) 而不是 c()。为了更简单地了解正在发生的事情,请查看 c(1, "a") 的结果。是数字还是字符?