I'm trying to build a dataset before plotting it. I decided to use function factory gammaplot.ff()
and the first version of my code looks like this:
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))
Turns out, the whole data frame contains character data, so I have to convert it back manually (took me a while to discover that in the first place!). SO search indicates that this happens because type variable is character. To avoid this (you can imagine performance issues on character data while building the data set!) I changed the code a bit:
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) } }
This works fine for me, but I lost a self-explanatory character parameter, which is a downside. Is there a way to keep the first version of function factory without an implicit conversion of all data to character?
If there's another way of achieving the same result, I'd be happy to try it out.
data. frame() instead of cbind() .
cbind() and rbind() both create matrices by combining several vectors of the same length. cbind() combines vectors as columns, while rbind() combines them as rows.
The cbind function is used to combine vectors, matrices and/or data frames by columns.
You can use rbind.data.frame
and cbind.data.frame
instead of rbind
and cbind
.
I want to put @mtelesha 's comment to the front.
Use stringsAsFactors = FALSE
in cbind
or 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"
UPDATE (May 5, 2020):
As of R version 4.0.0, R uses a stringsAsFactors = FALSE
default in calls to data.frame()
and read.table()
.
https://developer.r-project.org/Blog/public/2020/02/16/stringsasfactors/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With