Как отображать коэффициенты в научной нотации со стрельцом

Я хочу сравнить результаты различных моделей (lm, glm, plm, pglm) в таблице в R, используя stargazer или аналогичный инструмент. Однако я не могу найти способ отображения коэффициентов в научной нотации. Это своего рода проблема, потому что перехват довольно большой (около миллиона), в то время как другие коэффициенты малы (около e-7), что приводит к множеству бесполезных нулей, затрудняющих чтение таблицы.

Я нашел аналогичный вопрос: отображение модели модели в тексреге или stargazer R как научное. Но результаты там требуют перемасштабирования переменных, и поскольку я использую данные счетчика, я бы не хотел его перемасштабировать.

Я благодарен за любые предложения.

Ответ 1

Здесь воспроизводимый пример:

m1 <- lm(Sepal.Length ~ Petal.Length*Sepal.Width,
         transform(iris, Sepal.Length = Sepal.Length+1e6,
                   Petal.Length=Petal.Length*10, Sepal.Width=Sepal.Width*100))
# Coefficients:
#              (Intercept)              Petal.Length               Sepal.Width  Petal.Length:Sepal.Width  
#                1.000e+06                 7.185e-02                 8.500e-03                -7.701e-05  

Я не верю, что у stargazer есть легкая поддержка для этого. Вы могли бы попробовать другие альтернативы, такие как xtable или любой из многих вариантов здесь (я не пробовал их все)

library(xtable)
xtable(m1, display=rep('g', 5)) # or there 'digits' too; see '?xtable'

Или, если вы используете knitr или pandoc мне очень нравится pander, у которого уже есть автоматическая научная нотация (обратите внимание: это вывод pandoc, который выглядит как уценка, а не выход tex, а затем вы вязать или pandoc в латекс /pdf):

library(pander)
pander(m1)

Ответ 2

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

В то же время вы можете автоматически заменять числа в выводе научными обозначениями. Есть несколько вещей, которые нужно соблюдать при замене чисел. Важно не переформатировать числа, которые являются частью латексного кодирования. Кроме того, будьте осторожны, чтобы не заменить символы, которые являются частью имен переменных. Например в . в Sepal.Width может быть легко принята за число регулярным выражением. Следующий код должен иметь дело с наиболее распространенными ситуациями. Но если кто-то, например, X_123456789 свою переменную X_123456789 он может переименовать ее в X_1.23e+09 зависимости от настройки scipen. Таким образом, требуется некоторая осторожность, и, вероятно, потребуется внедрить более надежное решение в пакете stargazer.

Вот пример таблицы Stargazer для демонстрации (беззастенчиво скопированной с @математического .coffee):

library(stargazer)
library(gsubfn)
m1 <- lm(Sepal.Length ~ Petal.Length*Sepal.Width,
  transform(iris, Sepal.Length = Sepal.Length+1e6,
    Petal.Length=Petal.Length*10, Sepal.Width=Sepal.Width*100))    
star = stargazer(m1, header = F, digit.separator = '')

Теперь вспомогательная функция для переформатирования чисел. Вы можете поиграть с цифрами и параметрами scipen для управления выходным форматом. Если вы хотите использовать научный формат чаще, используйте меньшую (более отрицательную) область. В противном случае мы можем автоматически использовать научный формат только для очень маленьких или больших чисел, используя большую область scipen. Параметр cutoff предназначен для предотвращения переформатирования чисел, представленных только несколькими символами.

replace_numbers = function(x, cutoff=4, digits=3, scipen=-7) {
  ifelse(nchar(x) < cutoff, x, prettyNum(as.numeric(x), digits=digits, scientific=scipen))
}

И примените это к выводу gsubfn::gsubfn используя gsubfn::gsubfn

gsubfn("([0-9.]+)", ~replace_numbers(x), star)

enter image description here

Ответ 3

Другой надежный способ получить научную нотацию с помощью stargazer - взломать параметр digit.separator. Эта опция позволяет пользователю указать символ, который разделяет десятичные дроби (обычно точка . В большинстве локалей). Мы можем узурпировать этот параметр, чтобы вставить уникально идентифицируемую строку в любое число, которое мы хотим найти с помощью регулярных выражений. Преимущество поиска чисел таким образом состоит в том, что мы найдем только числа, которые соответствуют числовым значениям в выводе программы Stargazer. Т.е. нет возможности также сопоставлять числа, которые являются частью имен переменных (например, X_12345) или которые являются частью кода форматирования латекса (например, \hline \\[-1.8ex]). Далее я использую строку ::, но :: любая уникальная символьная строка (например, хеш), которую мы не найдем в других местах таблицы. Вероятно, лучше избегать использования каких-либо специальных символов регулярных выражений в метке идентификатора, поскольку это немного усложнит ситуацию.

Используя пример модели m1 из этого другого ответа.

mark  = '::::'
star = stargazer(m1, header = F, decimal.mark  = mark, digit.separator = '')

replace_numbers = function(x, low=0.01, high=1e3, digits = 3, scipen=-7, ...) {
  x = gsub(mark,'.',x)
  x.num = as.numeric(x)
  ifelse(
    (x.num >= low) & (x.num < high), 
    round(x.num, digits = digits), 
    prettyNum(x.num, digits=digits, scientific = scipen, ...)
  )
}    

reg = paste0("([0-9.\\-]+", mark, "[0-9.\\-]+)")
cat(gsubfn(reg, ~replace_numbers(x), star), sep='\n')

enter image description here

Обновление Если вы хотите убедиться, что конечные нули сохраняются в научной нотации, тогда мы можем использовать sprintf вместо prettyNum.

Как это

replace_numbers = function(x, low=0.01, high=1e3, digits = 3) {
  x = gsub(mark,'.',x)
  x.num = as.numeric(x)
  form = paste0('%.', digits, 'e')
  ifelse(
    (abs(x.num) >= low) & (abs(x.num) < high), 
    round(x.num, digits = digits), 
    sprintf(form, x.num) 
  )
}

enter image description here