-1

I am trying to find the row-wise minimum from a data frame of POSIXct. But using apply with which.min does not work:

df <- data.frame(date1 = as.POSIXct(c("2016-01-01", "2016-02-01")),
                 date2 = as.POSIXct(c("2015-10-01", "2016-06-01")))

apply(df, 1, which.min) # not OK
# integer(0)
# Warning messages:
# 1: In FUN(newX[, i], ...) : NAs introduced by coercion
# 2: In FUN(newX[, i], ...) : NAs introduced by coercion

apply(df, 1, function(x) which(x == min(x))) # OK
# [1] 2 1

sapply(1:nrow(df), function(i) which.min(df[i,])) # OK
# date2 date1 
# 2     1 

Can anybody explain this behaviour?

10 Rep
  • 2,217
  • 7
  • 19
  • 33
jlesuffleur
  • 1,113
  • 1
  • 7
  • 19
  • 1
    I think `apply` converts `df[1,]` with `as.matrix` which will result in the values being of type character which cannot be interpreted by `which.min`. – Martin Schmelzer Aug 04 '16 at 08:53

1 Answers1

2

Look at this:

str(apply(df, 1, identity))
# chr [1:2, 1:2] "2016-01-01" "2015-10-01" "2016-02-01" "2016-06-01"
# - attr(*, "dimnames")=List of 2
#  ..$ : chr [1:2] "date1" "date2"
#  ..$ : NULL

Applying identity turns the POSIXct values into characters! This happens because apply coerces its input into a matrix and as.matrix.data.frame uses format on POSIXct values because a matrix can only hold atomic values and S3 objects like POSIXct are not atomic. Thus the resulting matrix is a character matrix. And you can't calculate the minimum of characters. sapply iterates over its input and doesn't turn the data.frame into a matrix.

Roland
  • 127,288
  • 10
  • 191
  • 288
  • Ok, thanks. That is a bit strange because min function can be applied on a character vector. That means the which(x == min(x)) solution compares characters instead of POSIXcts and may give unexpected results! – jlesuffleur Aug 04 '16 at 09:17