Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 444
ricardo Avatar asked Dec 13 '22 00:12

ricardo


2 Answers

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
like image 143
A5C1D2H2I1M1N2O1R2T1 Avatar answered Jan 07 '23 12:01

A5C1D2H2I1M1N2O1R2T1


It was suggested I turn my comment into an answer.

In your R console, when you type head(m, 5), what you see printed on your screen is really the result of print(head(m, 5)). So if this is what you want your output to look like, consider using the print function rather than cat when displaying the head and tail of your objects:

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

m <- matrix(1:10, 20)
ht(m)
# head -->
#      [,1]
# [1,]    1
# [2,]    2
# [3,]    3
# [4,]    4
# [5,]    5
# --------
# tail -->
#       [,1]
# [16,]    6
# [17,]    7
# [18,]    8
# [19,]    9
# [20,]   10

I find @mrdwab's answer to be a very elegant solution. It does not explicitly use print, instead returns a list. However, when his function is called from the R console and the output is not assigned to anything, then it is printed to the console (hence print is used implicitly). I hope that helps you understand what's going on.

like image 31
flodel Avatar answered Jan 07 '23 14:01

flodel