Home > database >  Using R, `print` function, how to include/exclude colnames or position them?
Using R, `print` function, how to include/exclude colnames or position them?

Time:08-13

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 =.

  • Related