Reputation: 72683
The question probably generalizes to printing any type of multiline output, and keeping the columns aligned. My actual issue concerns the output of summary.default
.
I'm trying to add indentation of a multiple of two to cat
output of the summary.default
function. I've made some attempts using cat
and print
, also consulting some related answers, but they all fail so far.
f <- function(x) {
s <- summary.default(x)
liner <- Reduce(paste0, rep("-", 70))
cat("\n", liner, "\n") ## ATT 1. -------------------------------
cat("\n", "foo first attempt", "\n")
cat("\n--|\n")
print(round(s, 3)) #
cat("\n----|\n")
cat("\n *additional information\n")
cat("\n", liner, "\n") ## ATT 2. -------------------------------
cat("\n", "foo second attempt", "\n")
cat("\n--|\n")
print(unname(as.data.frame(cbind(" ", t(attr(s, "names"))))), row.names=F) #
print(unname(as.data.frame(cbind(" ", t(round(unclass(s), 3))))), row.names=F) #
cat("\n----|\n")
cat("\n *additional information\n")
cat("\n", liner, "\n") ## ATT 3. -------------------------------
cat("\n", "foo third attempt", "\n")
cat("\n--|\n")
cat("\n ", attr(s, "names"), "\n")
cat("\n ", round(s, 3), "\n") #
cat("\n----|\n")
cat("\n *additional information\n")
}
> x <- rnorm(100)
> f(x)
----------------------------------------------------------------------
foo first attempt
--|
Min. 1st Qu. Median Mean 3rd Qu. Max.
-2.069 -0.654 -0.092 -0.075 0.696 1.997
----|
*additional information
----------------------------------------------------------------------
foo second attempt
--|
Min. 1st Qu. Median Mean 3rd Qu. Max.
-2.069 -0.654 -0.092 -0.075 0.696 1.997
----|
*additional information
----------------------------------------------------------------------
foo third attempt
--|
Min. 1st Qu. Median Mean 3rd Qu. Max.
-2.069 -0.654 -0.092 -0.075 0.696 1.997
----|
*additional information
The ---|
symbolize the required indentation. First attempt does not have any indentation. Second attempt is better, but there's additional space between the lines, and does not generalize when rounding to different digits. At attempt 3 the columns are no longer aligned.
How can I get the desired output using features that come with R?
----------------------------------------------------------------------
foo some text
Min. 1st Qu. Median Mean 3rd Qu. Max.
-2.069 -0.654 -0.092 -0.075 0.696 1.997
*additional information
Upvotes: 3
Views: 693
Reputation: 449
For this task you can use two function of base r consecutively. There is the function capture.output
which captures the output of a command like print. Using paste
to combine the desired number of spaces, it can be written to stdout with writelines
, which preserves the line structure of the dataframe printout.
To do the above a combined all your information given in the printout as an example to a data.frame (df).
df = data.frame("Min."=-2.069, "First Qu."= -0.654, "Median"= -0.092 , "Mean" =-0.075, "Third Qu."= 0.696, "Max."= 1.997 )
writeLines(paste0(" ", capture.output(print(df, row.names = F))))
I added roe.names = F, to suppress printing the row numbers of the dataframe
Upvotes: 2
Reputation: 6485
The only thing I could come up with was to manually re-assemble the 'summary' output to account for the different 'cell' widths:
add_indent_and_right_align <- function(summry, indent=2, minDist= 2, rounding = 3) {
# add an indent and then right-align summary output table
#
# summry - summary object
# indent - integer Number of spaces to add before summary output
# minDist . integer Minimal number of spaces between two columns
# rounding - integer Number of decimals to round summary to
header <- attr(summry, "names")
value <- round(summry, 3)
r = list()
for (i in seq_along(header)) {
# find out how wide the column has to be
# to fit header and value and indent (if first column) or minDist
#
max_len <- max(nchar(header[i]), nchar(value[i]))
if (i == 1) {
cell_width <- max_len + indent
r[1] <- paste0(paste0(rep(" ", cell_width - nchar(header[i])), collapse=""), header[i])
r[2] <- paste0(paste0(rep(" ", cell_width - nchar(value[i])), collapse=""), value[i])
} else {
cell_width <- max_len + minDist
r[1] <- paste0(r[1], paste0(rep(" ", cell_width - nchar(header[i])), collapse=""), header[i])
r[2] <- paste0(r[2], paste0(rep(" ", cell_width - nchar(value[i])), collapse=""), value[i])
}
}
return(paste0(r, collapse="\n"))
}
f <- function(x) {
indent <- 4 # how many spaces shoud the whole summary output be indented?
s <- summary.default(x)
cat(paste0(rep("-", 70), collapse=""), "\n")
cat("\n")
cat("foo some text", "\n")
cat("\n")
cat(add_indent_and_right_align(summry=s, indent=4, minDist= 1, rounding = 3), "\n")
cat("\n")
cat(paste0(paste0(rep(" ", indent), collapse=""), "*additional information"), "\n")
cat("\n")
}
set.seed(1)
x <- rnorm(100)
f(x)
Returns:
---------------------------------------------------------------------- foo some text Min. 1st Qu. Median Mean 3rd Qu. Max. -2.215 -0.494 0.114 0.109 0.692 2.402 *additional information
Upvotes: 2