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?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With