I need to "convert" a data.frame
object into plain text (like the print
output to the console.
So far I created the following function (using the stringr
package) but I wonder if an already implemented function or a more efficient approach exists:
toString.data.frame = function(object, ...) {
maxLen = max(
stringr::str_length(apply(object, c(1,2), as.character)),
stringr::str_length(names(object))
);
# data-frame to character matrix
txt = apply(object, c(1,2), stringr::str_pad, width=maxLen+5, side="left");
# concatenate the columns
txt = apply(txt, 1, paste, collapse="");
# concatenate the rows
txt = paste(txt, collapse="\n");
# add column names
txt = paste( # concatenate header and body
paste( # concatenate all the headers
stringr::str_pad( # add 5 spaces on the left of each header
stringr::str_pad(names(object), width=maxLen, side="right") # fill each header
, width=maxLen+5, side="left")
, collapse="")
, txt
, sep="\n");
return(txt);
}
I add some runnable code as well as an output example (each output row is delimited by "|")
df = data.frame(hello=rnorm(1:15), world=rnorm(1:15));
cat(toString(object), "\n");
| a b |
| 0.217785930312173 1.35892062758937|
| -0.0529272009376736 -1.3537444650507|
| -0.0914533595349014 -0.283164123247757|
| 0.209099248751634 -0.994596208802379|
| 1.41207193727609 0.754568758899429|
| 0.0271570788346636 0.722728545001598|
| 1.09160395973882 -0.466194711071017|
| -0.676012596015548 0.247534965195453|
| 0.36022565974381 -0.318822054653857|
| 0.330251755314496 -0.379818935427323|
| 1.29858423625996 0.393100959746072|
| 1.79061048596737 0.124484229714237|
| -0.636849202004066 -1.48651181772674|
| 1.08795175312078 0.231693241998673|
| -0.810214549466222 -0.753200696904484|
I think it will be simpler to use sink
and textConnection
, and a bit of manual formatting for your desired effect.
df = data.frame(hello=rnorm(1:15), world=rnorm(1:15));
tc <- textConnection("str", "w")
sink(tc) # divert output to tc connection
print(df) # print in str string instead of console
sink() # set the output back to console
close(tc) # close connection
str <- substr(str,floor(length(str)/10)+3,nchar(str[1])) # we get rid of the row numbers that come with print
str <- paste0("| ",str,"|",collapse="\n") # we build a proper unique string with your pipes and new lines
cat(str)
# | hello world|
# | 1.35547838 0.69280925|
# | 0.61364635 1.84942722|
# | -0.23441769 0.10034022|
# | 1.73325659 -0.22303366|
# | -0.65542783 -0.47574465|
# | -0.87341058 -0.63579176|
# | 0.04449579 0.36899672|
# | -1.00486219 1.25508269|
# | -0.23235707 1.18740340|
# | -0.46296889 0.88100960|
# | 0.52494728 0.20217947|
# | 0.94017525 0.01272363|
# | -0.09997728 0.22612848|
# | -0.04388133 -0.49271157|
# | -1.09953287 -0.27971771|
After having a look at the print.data.frame
function I dare say the following may be a better solution (better formatting and it's almost the same code of a well-tested bult-in function)
toString.data.frame = function (object, ..., digits=NULL, quote=FALSE, right=TRUE, row.names=TRUE) {
nRows = length(row.names(object));
if (length(object)==0) {
return(paste(
sprintf(ngettext(nRows, "data frame with 0 columns and %d row", "data frame with 0 columns and %d rows")
, nRows)
, "\\n", sep = "")
);
} else if (nRows==0) {
return(gettext("<0 rows> (or 0-length row.names)\\n"));
} else {
# get text-formatted version of the data.frame
m = as.matrix(format.data.frame(object, digits=digits, na.encode=FALSE));
# define row-names (if required)
if (isTRUE(row.names)) {
rowNames = dimnames(object)[[1]];
if(is.null(rowNames)) {
# no row header available -> use row numbers
rowNames = as.character(1:NROW(m));
}
# add empty header (used with column headers)
rowNames = c("", rowNames);
}
# add column headers
m = rbind(dimnames(m)[[2]], m);
# add row headers
m = cbind(rowNames, m);
# max-length per-column
maxLen = apply(apply(m, c(1,2), stringr::str_length), 2, max, na.rm=TRUE);
# add right padding
## t is needed because "If each call to FUN returns a vector of length n, then apply returns an array of dimension c(n, dim(X)[MARGIN])"
m = t(apply(m, 1, stringr::str_pad, width=maxLen, side="right"));
m = t(apply(m, 1, stringr::str_pad, width=maxLen+3, side="left"));
# merge columns
m = apply(m, 1, paste, collapse="");
# merge rows (and return)
return(paste(m, collapse="\n"));
}
}
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