Почему применение суммы по столбцам и colSums отличается, когда dataframe содержит формат даты?

#r #date #sum #apply #lubridate

#r #Дата #сумма #применить #lubridate

Вопрос:

В приведенном ниже примере, почему A не равно B ? Проблема связана со столбцом даты, поскольку AA = BB, но я не могу понять почему…

 library(lubridate)
MM=data.frame(ID=1:3,Date=ymd(c("2019-11-07","2019-11-07","2019-11-13")),X=c(-1,1,1),Y=c(1,-1,-1))
A=apply(MM,2,function(x) sum(x>0))
B=colSums(MM>0)
A
# ID Date    X    Y
# 3    3    0    0 
B
# ID Date    X    Y 
# 3    3    2    1
AA=apply(MM[,-2],2,function(x) sum(x>0))
BB=colSums(MM[,-2]>0)
AA
# ID  X  Y 
# 3  2  1 
BB
# ID  X  Y 
# 3  2  1 
  

R версия 4.0.3 (2020-10-10)

Ответ №1:

Это потому apply , что перед применением функции к каждому столбцу сначала преобразуется data.frame в матрицу.

Поэтому:

 > as.matrix(MM)

     ID  Date         X    Y   
[1,] "1" "2019-11-07" "-1" " 1"
[2,] "2" "2019-11-07" " 1" "-1"
[3,] "3" "2019-11-13" " 1" "-1"
  

Все преобразуется в символ.

В частности, вы можете видеть, что:

 > " 1" > 0
[1] FALSE
> "1" > 0
[1] TRUE
  

Это потому, что 0 преобразуется в char .

«0» стоит перед «1» в алфавитном порядке, потому что символ 0 сравнивается с пробелом вместо символа «1».

Порядок строк определяется путем сравнения символа за символом 1 на 1. (это та же причина, почему "10" > "9" FALSE , потому 1 что в алфавитном порядке перед 9 ).

 > sort(c("0", " 1"))
[1] " 1" "0" 
> sort(c("0", "1"))
[1] "0" "1"
  

Как следствие:

 > as.matrix(MM)>0
       ID Date     X     Y
[1,] TRUE TRUE FALSE FALSE
[2,] TRUE TRUE FALSE FALSE
[3,] TRUE TRUE FALSE FALSE
  

colSums этого не делает.


Вы можете получить тот же результат colSums , что и при выполнении:

 > apply(MM>0, 2, sum)
  ID Date    X    Y 
   3    3    2    1 
  

Комментарии:

1. Напротив, MM > 0 работает с целочисленными значениями, лежащими Date в основе объекта.

2. sapply этого тоже не делает, поэтому sapply(MM, function(x) sum(x>0)) работает по назначению.

3. И все приведено к символьной матрице (не «дата-время»).

4. Хорошо! Спасибо! Но в чем тестируется as.matrix(MM)[1] > 0 ? Почему "1">0 возвращает TRUE, а " 1">0 не нет?