Нечетное поведение с медианным()?

Я замечаю некоторое противоречивое поведение при применении функции median() к dataframes. "Непоследовательное поведение" обычно означает, что я что-то не понимаю, поэтому, надеюсь, кто-то захочет прояснить это для меня.

Я понимаю, что некоторые функции (например, min(), max()) преобразуют данные в вектор и возвращают соответствующее значение для всего df, а mean() и sd() возвращают значение для каждого столбца. Хотя это немного запутывает, эти различия в поведении не вызывают много проблем, поскольку большинство кода будет ломаться, если скаляр возвращается вместо вектора. Однако median() кажется непоследовательным. Например:

dat <- data.frame(x=1:100, y=2:101)
median(dat)

Возвращает вектор: [1] 50.5 51.5

Но иногда он ломается:

dat2 <- data.frame(x=1:100, y=rnorm(100))
median(dat2)

Возвращает: [1] NA NA Warning messages: 1: In mean.default(X[[1L]], ...) : argument is not numeric or logical: returning NA 2: In mean.default(X[[2L]], ...) : argument is not numeric or logical: returning NA

Однако median(dat2$x) и median(dat2$y) дают правильный результат.

Также рассмотрим следующее:

dat3 <- data.frame(x=1:100, y=1:100)
dat4 <- data.frame(x=1:100, y=100:199)

В приведенном выше примере median(dat3) возвращает [1] 50.5 NA, а median(dat4) возвращает [1] 50.5 149.5! Я бы ожидал, что обе или ни одна из них не сработает. Итак, я явно не понимаю, как работает функция median().

Кроме того, функции, такие как sd, mean(), min() и max(), дают ожидаемые (если кажутся непоследовательными) результаты во всех вышеперечисленных случаях.

Я знаю, что я могу использовать что-то вроде sapply(dat2, median), чтобы получить нужный результат, но мне интересно, почему боги R решили реализовать эти основные функции статистики таким образом, чтобы, по крайней мере, на поверхности, казалось непоследовательным. Я подозреваю, что я и, возможно, другие неофиты, вероятно, не понимают фундаментальную концепцию, и я был бы признателен вам за понимание.

Ответ 1

Это точное явление недавно обсуждалось в потоке медианы и данных на R-devel. Консенсус, похоже, заключался в том, что метод mean.data.frame должен быть устаревшим, и пользователи должны полагаться на sapply.

Ответ 2

median не имеет метода для объектов класса data.frame, в отличие от mean. Используйте функцию plyr и colwise для достижения желаемого результата. Или используйте семейство функций *apply.

> sapply(mtcars, median)                                                                                                     
    mpg     cyl    disp      hp    drat      wt    qsec      vs      am    gear                                              
 19.200   6.000 196.300 123.000   3.695   3.325  17.710   0.000   0.000   4.000                                              
   carb                                                                                                                      
  2.000                                                                                                                      
> colwise(median)(mtcars)                                                                                                    
   mpg cyl  disp  hp  drat    wt  qsec vs am gear carb                                                                       
1 19.2   6 196.3 123 3.695 3.325 17.71  0  0    4    2 

Ответ 3

Самый простой способ - это пакет miscTools

> library(miscTools)
> dat3 <- data.frame(x=-50:50, y=(-50:50)^2)
> colMedians(dat3)
  x   y 
  0 625 

что является правильным, в отличие от

> median(dat3)
[1]   0 850

Пакет matrixStats также имеет функцию colMedians, но не для фреймов данных.