Как превратить формулу в переменные для использования с функцией fastLm в R

#r #data.table #rcpparmadillo

#r #данные.таблица #rcpparmadillo

Вопрос:

Я пытаюсь использовать функцию RcppArmadillo::fastLM вместо из lm соображений производительности. Вот мой вызов функции для lm

 test_dt = structure(list(A= c(168.08, 166.65, 167.52, 167.16, 165.77,  167.65, 169.84, 170.45, 171.29, 173.15, 174.12, 174.45, 174.18,  172.92, 174.5, 173.94, 172.61, 168.74, 167.28, 167.12), `B` = c(1801.599976,  1783, 1795.099976, 1788.699951, 1763.599976, 1793, 1816.400024,  1827.400024, 1830.199951, 1847.599976, 1863.199951, 1867.900024,  1866.099976, 1853.599976, 1869.699951, 1861, 1851.199951, 1806,  1783.5, 1784.099976)), row.names = c(NA, -20L), class = c("data.table",  "data.frame"))  coef(lm(A ~ B   0,data = test_dt))[1]  gt; 0.0934728   

поскольку большая часть времени используется lm при интерпретации формулы, я не хочу использовать формулу. Вместо этого я хочу превратить это во что-то —

 RcppArmadillo::fastLM(X = test_dt$B   0, y = test_dt$A)  

но я не уверен, как добавить 0 , как показано в формуле.

Я попробовал следующее

 library(data.table) dt = copy(test_dt) dt[, C := 0] coef(RcppArmadillo::fastLm(X = dt[,2:3], y = dt[,1]))[[1]]  

Но это дает ошибку.

 Error in fastLm.default(X = dt[, 2:3], y = dt[, 1]) :   (list) object cannot be coerced to type 'double'  

Может ли кто-нибудь показать мне правильный способ превращения формулы A ~ B 0 в переменные X и y для использования в функции fastLm?

Вот результаты работы.

 microbenchmark::microbenchmark(  formula = coef(lm(A ~ B   0, dt))[1],  fastLm = with(dt, coef(RcppArmadillo::fastLm(B, A)))[1],  flm = with(dt, collapse::flm(A, cbind(B)))[1],  times = 100)  
 Unit: microseconds  expr min lq mean median uq max neval cld  formula 1157.822 1173.249 1191.57071 1183.0080 1197.5560 1714.430 100 c  fastLm 219.785 228.086 240.30415 235.2545 244.7465 405.353 100 b   flm 67.595 71.902 76.91765 74.7790 77.2050 228.320 100 a   

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

1. Можете ли вы попробовать метод формулы, т. е. fastLm(A ~ B 0, data = dt)

2. Метод формулы работает нормально. Единственная проблема заключается в том, что использование формулы в 3 раза медленнее.

3. В первой формуле , которую вы использовали A ~ B 0 , но во второй вы используете y как B , это опечатка

4. Да, это была опечатка, я ее исправил. Спасибо.

5. Вам нужно fastLm(X = dt[, 2:3], y = dt[[1]])

Ответ №1:

Первым аргументом метода fastLm по умолчанию является матрица модели. Он должен иметь столбец 1 для представления перехвата, а если это не так, то перехвата нет.

Они дают один и тот же ответ, не используя перехват:

 coef(lm(A ~ B   0, test_dt))[1] with(test_dt, coef(fastLm(B, A)))  

и они дают один и тот же ответ, используя перехват:

 coef(lm(A ~ B, test_dt)) with(test_dt, coef(fastLm(cbind(1, B), A)))  

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

1. Спасибо, @Grothendieck, это сработало идеально. Я поделился результатами работы выше.

2. Вы также можете попробовать flm в пакете свернуть. Он использует те же аргументы, что и fastLm, но в обратном порядке, и возвращает только коэффициенты, поэтому с ним не используется coef.

3. Спасибо за указатель. Я пытался library(collapse) with(dt, collapse::flm(X = B, y = A, method = "lm")) , но это ошибка if (n != NROW(y)) stop("NROW(y) must match nrow(X)") . Похоже, что внутри flm функционируют оба dim(dt$A) и nrow(dt$B) терпят неудачу.

4. Используя test_dt из вопроса, они оба работают для меня: library(collapse); with(test_dt, flm(A, cbind(B))) - кажется, что B не может быть вектором, но должен быть матрицей, и используя ту же инструкцию библиотеки: with(test_dt, flm(A, cbind(1, B)))

5. Вау, flm это еще быстрее. Я обновил результаты работы. Большое вам спасибо!

Ответ №2:

Это y должен быть вектор. Согласно с ?fastLm

y - вектор, содержащий объясняемую переменную.

С помощью dt[,1] , drop = FALSE в data.table котором возвращает таблицу data.table с одним столбцом. Вместо этого, если нам нужен вектор, используйте [[ для извлечения столбца

 fastLm(X = dt[, 2:3], y = dt[[1]])  

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

1. Есть ли способ удалить предупреждение? solve(): system is singular; attempting approx solution

2. @Saurabh когда вы говорите удалить предупреждение, вы хотите suppressWarnings

3. Нет :), я имел в виду, есть ли что-то еще, что я делаю неправильно во время звонка fastLm . Я попытался превратить X в матрицу, но ошибка все равно есть.