user1700890
user1700890

Reputation: 7730

Dropping last n rows in dataframe (dropping zero rows) in R

So if I would like to drop n last rows in dataframe, I would write

head(df, -n)

It works file for all n's except 0. Does anybody know why?

head(df, -0)

will return empty dataframe.

0 needs to be handled separately. ;-(

Upvotes: 1

Views: 1278

Answers (2)

G. Grothendieck
G. Grothendieck

Reputation: 269694

As already indicated in the comments it is because -0 equals 0 and head(df, 0) means return zero rows. In the signed zero section below we explore this further.

Remove n rows even if n is zero

First, a simple workaround is the following which removes the last n rows even if n equals zero:

head(df, nrow(df) - n)

Signed zero

On the other hand, in floating point (but not integer arithmetic) there actually is such a thing as signed zero. Consider this version of head which removes 0 rows if n = -0 and returns 0 rows if n is +0:

is_minus_zero <- function(x) identical(x, 0) && sign(1/x) == -1
head2 <- function(x, n) {
  if (is_minus_zero(n)) df
  else head(x, n)
}

head2(BOD, 0)
## [1] Time   demand
## <0 rows> (or 0-length row.names)

head2(BOD, -0)
##   Time demand
## 1    1    8.3
## 2    2   10.3
## 3    3   19.0
## 4    4   16.0
## 5    5   15.6
## 6    7   19.8

Upvotes: 1

LyzandeR
LyzandeR

Reputation: 37879

head is just a convenience function for [:

getAnywhere(head.data.frame)
#function (x, n = 6L, ...) 
#{
#    stopifnot(length(n) == 1L)
#    n <- if (n < 0L) 
#        max(nrow(x) + n, 0L)
#    else min(n, nrow(x))
#    x[seq_len(n), , drop = FALSE]
#}

And as you can see n ends up subsetting the data.frame. zero or negative zero will return the structure of the data.frame in R. This is how it is intended.

However, it is quite easy to write your own head function:

head2 <- function(df, n) {

  #or do anything else
  if (n == 0L | n == -0L) return(df)
  head(df, n)

}
head2(iris, -5) #works as normal
head2(iris, -0) #returns whole df

Upvotes: 2

Related Questions