避免rbind()/ cbind()从数字转换为因子

ton*_*nov 33 r

我正在尝试在绘制数据集之前构建数据集.我决定使用函数工厂gammaplot.ff(),我的代码的第一个版本如下所示:

PowerUtility1d <- function(x, delta = 4) {
  return(((x+1)^(1 - delta)) / (1 - delta))
}
PowerUtility1d <- Vectorize(PowerUtility1d, "x")

# function factory allows multiparametrization of PowerUtility1d()
gammaplot.ff <- function(type, gamma) {
  ff <- switch(type, 
               original = function(x) PowerUtility1d(x/10, gamma),
               pnorm_wrong = function(x) PowerUtility1d(2*pnorm(x)-1, gamma),
               pnorm_right = function(x) PowerUtility1d(2*pnorm(x/3)-1, gamma)
              )
  ff
}

gammaplot.df <- data.frame(type=numeric(), gamma=numeric(), 
                           x=numeric(), y=numeric())
gammaplot.gamma <- c(1.1, 1.3, 1.5, 2:7)
gammaplot.pts <- (-1e4:1e4)/1e3

# building the data set
for (gm in gammaplot.gamma) {
   for (tp in c("original", "pnorm_wrong", "pnorm_right")) {
     fpts <- gammaplot.ff(tp, gm)(gammaplot.pts)    
     dataChunk <- cbind(tp, gm, gammaplot.pts, fpts)
     colnames(dataChunk) <- names(gammaplot.df)
     gammaplot.df <- rbind(gammaplot.df, dataChunk)
   }
}

# rbind()/cbind() cast all data to character, but x and y are numeric
gammaplot.df$x <- as.numeric(as.character(gammaplot.df$x))
gammaplot.df$y <- as.numeric(as.character(gammaplot.df$y))
Run Code Online (Sandbox Code Playgroud)

事实证明,整个数据框包含字符数据,所以我必须手动将其转换回来(我花了一些时间才发现它!).SO搜索表明发生这种情况是因为类型变量是字符.为了避免这种情况(您可以在构建数据集时想象字符数据的性能问题!)我稍微更改了代码:

gammaplot.ff <- function(type, gamma) {
  ff <- switch(type, 
               function(x) PowerUtility1d(x/10, gamma),
               function(x) PowerUtility1d(2*pnorm(x)-1, gamma),
               function(x) PowerUtility1d(2*pnorm(x/3)-1, gamma)
              )
  ff
}

for (gm in gammaplot.gamma) {
  for (tp in 1:3) {
    fpts <- gammaplot.ff(tp, gm)(gammaplot.pts)    
    dataChunk <- cbind(tp, gm, gammaplot.pts, fpts)
    colnames(dataChunk) <- names(gammaplot.df)
    gammaplot.df <- rbind(gammaplot.df, dataChunk)
  }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说很好,但我丢失了一个不言自明的字符参数,这是一个缺点.有没有办法保留函数工厂的第一个版本而不将所有数据隐式转换为字符?

如果有另一种方法可以达到相同的效果,我很乐意尝试一下.

sha*_*dow 68

你可以使用rbind.data.framecbind.data.frame不是rbindcbind.

  • `cbind.data.frame(tp,gm,gammaplot.pts,fpts,stringsAsFactors = FALSE)`如果你没有stringsAsFactors = F,你仍然可以有因子. (9认同)
  • 注意:当将`cbind.data.frame()`与名单一起使用时,你将创建焦虑矩阵,你并不打算.在使用`cbind.data.frame()`而不是`cbind()`之前,这不是预期的,只是`unlist()`命名列表. (2认同)

HBa*_*Bat 8

我想把@mtelesha 的评论放在前面。

stringsAsFactors = FALSEcbind或 中使用cbind.data.frame

x <- data.frame(a = letters[1:5], b = 1:5)
y <- cbind(x, c = LETTERS[1:5])
class(y$c)
## "factor"
y <- cbind.data.frame(x, c = LETTERS[1:5])
class(y$c)
## "factor"
y <- cbind(x, c = LETTERS[1:5], stringsAsFactors = FALSE)
class(y$c)
## "character"
y <- cbind.data.frame(x, c = LETTERS[1:5], stringsAsFactors = FALSE)
class(y$c)
## "character"
Run Code Online (Sandbox Code Playgroud)

更新(2020 年 5 月 5 日):

从 R 版本 4.0.0 开始,RstringsAsFactors = FALSE在调用data.frame()和 时使用默认值read.table()

https://developer.r-project.org/Blog/public/2020/02/16/stringsasfactors/