Search code examples
rdataframetailheadcat

combining head and tail methods in R


I use the head(d) and tail(d) methods in R package utils a lot - frequently one after the other. So I wrote a simple wrapper for the two functions:

    ht <- function(d, m=5, n=m){
      # print the head and tail together
      cat(" head -->  ", head(d,m), "\n", "--------", "\n", "tail -->  ", tail(d,n), "\n")
    }

And I got some unexpected results. Can someone please help me understand why? (so i can fix it or at least understand your solution!).

Some background...

Numeric values work fine:

x <- 1:100
ht(x)

So does complex:

ni <- as.complex(1:100)
ht(ni)

and characters:

ll <- letters[1:26]
ht(ll)

Matrix loses it's structure, returning [1,1] to [5,5] + [16,1] to [20,5] but as two vectors -- compare:

m <- matrix(1:10, 20)
ht(m)

to:

head(m, 5)
tail(m,5)

I would like to keep the matrix structure, as the utils methods does - is this possible?

Finally (well, there may be more bugs, this is just where I'm up to) data.frames are a mess:

df <- data.frame(num=x[1:26], char=ll)
ht(df)

This yields the following error:

head -->   Error in cat(list(...), file, sep, fill, labels, append) :   
  argument 2 (type 'list') cannot be handled by 'cat'

Steps so far:

As the utils method keeps the matrix tidy when done in bits, I tried to fix the problem with the following edit:

function(d, m=5, n=m){
  # print the head and tail together
  rb <- rbind(head(d, m), tail(d,n))
  if (class(d) == 'matrix'){
    len <- nrow(rb)
    cat(" head -->  ", rb[(1:m),], "\n", "--------", "\n", "tail -->  ", rb[((len-n):len),], "\n")
  }
  else cat(" head -->  ", rb[1,], "\n", "--------", "\n", "tail -->  ", rb[2,], "\n")
}

Which does not seem to have done anything to the matrix and still breaks with the same error when I use:

ht(df)

I am guessing from the errors that there is some issue with cat() here, but I cannot figure out what it is or how to fix it.

Can anyone please help?


Solution

  • Why not modify your function to output a list instead?

    ht <- function(d, m=5, n=m){
      # print the head and tail together
      list(HEAD = head(d,m), TAIL = tail(d,n))
    }
    

    Here's the output for your matrix and data.frame:

    ht(matrix(1:10, 20))
    # $HEAD
    #      [,1]
    # [1,]    1
    # [2,]    2
    # [3,]    3
    # [4,]    4
    # [5,]    5
    # 
    # $TAIL
    #       [,1]
    # [16,]    6
    # [17,]    7
    # [18,]    8
    # [19,]    9
    # [20,]   10
    
    ht(data.frame(num=x[1:26], char=ll))
    # $HEAD
    #   num char
    # 1   1    a
    # 2   2    b
    # 3   3    c
    # 4   4    d
    # 5   5    e
    # 
    # $TAIL
    #    num char
    # 22  22    v
    # 23  23    w
    # 24  24    x
    # 25  25    y
    # 26  26    z