Motivation
The head
function of base
doesn't have a SKIP or RANGE feature, so I was writing a function to do that:
df.printHead = function(df, n=6, row.idx=1, ...)
{
idx = row.idx; ## offset, e.g, SKIP
nrow = nrow(df);
# tails
lower = (idx - n); if(lower < 1) { lower = 1; }
upper = lower n; if(upper > nrow) { upper = nrow; }
if(upper >= idx) { upper = idx - 1; }
tails = df[ lower:upper, ]; rownames(tails) = lower:upper;
print(tails, col.names=TRUE, col.at="top", ...);
cat("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "\n");
# one
one = df[idx, ]; rownames(one) = idx;
print(one, col.names=FALSE, ...);
cat("\n");
cat("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "\n");
# heads
upper = (idx n); if(upper > nrow) { upper = nrow; }
lower = upper - n; if(lower < 1) { lower = 1; }
if(lower <= idx) { lower = idx 1; }
heads = df[ lower:upper , ]; rownames(heads) = lower:upper;
print(heads, col.names=TRUE, col.at="bottom", ...);
invisible(list("tails"=tails, "one"=one, "heads"=heads));
}
Examples (iris)
dim(iris);
df.printHead(iris, n=6, row.idx=4);
df.printHead(iris, n=6, row.idx=148);
What output I get
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
142 6.9 3.1 5.1 2.3 virginica
143 5.8 2.7 5.1 1.9 virginica
144 6.8 3.2 5.9 2.3 virginica
145 6.7 3.3 5.7 2.5 virginica
146 6.7 3.0 5.2 2.3 virginica
147 6.3 2.5 5.0 1.9 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
148 6.5 3 5.2 2 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
149 6.2 3.4 5.4 2.3 virginica
150 5.9 3.0 5.1 1.8 virginica
What output I want
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
142 6.9 3.1 5.1 2.3 virginica
143 5.8 2.7 5.1 1.9 virginica
144 6.8 3.2 5.9 2.3 virginica
145 6.7 3.3 5.7 2.5 virginica
146 6.7 3.0 5.2 2.3 virginica
147 6.3 2.5 5.0 1.9 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148 6.5 3 5.2 2 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
149 6.2 3.4 5.4 2.3 virginica
150 5.9 3.0 5.1 1.8 virginica
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
RTFM
The alignment left-to-right is nice, since all of the data in print is coming from the same dataframe. I am aware I can use cat
and fully control the output.
I am searching for a print
solution as it best integrates with base
https://rdrr.io/r/base/print.dataframe.html
This calls format which formats the data frame column-by-column,
then converts to a character matrix and dispatches
to the print method for matrices.
Question
I have tried col.names=TRUE
inside of print
I have also added col.at="bottom"
and DEFAULT col.at="top"
for the location if TRUE
print
has the dots ...
so do I need to write my own Rcpp code or something to get this to work?
Can I extend
the print.matrix formatting that works internally in R? Can I write my own formatter
that hooks into the base
? If so how?
CodePudding user response:
We could utilize capture.output()
and restructure it with cat(..., sep = "\n")
:
df.printHead = function(df, n=6, row.idx=1, ...)
{
idx = row.idx; ## offset, e.g, SKIP
nrow = nrow(df);
# tails
lower = (idx - n); if(lower < 1) { lower = 1; }
upper = lower n; if(upper > nrow) { upper = nrow; }
if(upper >= idx) { upper = idx - 1; }
tails = df[ lower:upper, ]; rownames(tails) = lower:upper;
print(tails);
cat("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "\n");
# one
one = df[idx, ]; rownames(one) = idx;
printone <- capture.output(print(one));
cat("\n");
cat(printone[-1], sep = "\n");
cat("\n");
cat("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "\n");
# heads
upper = (idx n); if(upper > nrow) { upper = nrow; }
lower = upper - n; if(lower < 1) { lower = 1; }
if(lower <= idx) { lower = idx 1; }
heads = df[ lower:upper , ]; rownames(heads) = lower:upper;
printheads <- capture.output(print(heads));
cat(printheads[-1], sep = "\n");
cat(printheads[1], sep = "\n");
invisible(list("tails"=tails, "one"=one, "heads"=heads));
}
Output:
df.printHead(iris, n=6, row.idx=148)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
142 6.9 3.1 5.1 2.3 virginica
143 5.8 2.7 5.1 1.9 virginica
144 6.8 3.2 5.9 2.3 virginica
145 6.7 3.3 5.7 2.5 virginica
146 6.7 3.0 5.2 2.3 virginica
147 6.3 2.5 5.0 1.9 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148 6.5 3 5.2 2 virginica
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
149 6.2 3.4 5.4 2.3 virginica
150 5.9 3.0 5.1 1.8 virginica
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
If you want you could of course make a function out of taking the arguments col.names
and col.at
. There is no need for all your ;
's <-
is usually preferred over =
.