Как обрабатывать имена строковых переменных во вложенной формуле в r - PullRequest
0 голосов
/ 02 мая 2020

Я пытаюсь запустить loop из lm регрессий со списком имен переменных. Пожалуйста, смотрите код ниже.

order <- c(4, 6, 8, 10, 12, 14, 16) # position of variables in my data frame

for(i in order) {
  m7 <- df %>% filter(names(df)[i] > 0) %>% 
    pdata.frame(index=c("index","Year")) %>% 
    plm(formula= log(names(df)[i]) ~ log(names(df)[i-1]) + 
          frez + log(dd) + I((log(dd))^2) + 
          preci + I(preci^2) + 
          + m7 + max.c + spei + lt + qt, 
        data=., effect = c("individual"),model = "within") %>% 
    coeftest(., vcov = function(x) vcovHC(x, method = 'arellano', cluster = 'group', type = 'HC3'))
}

Я получил сообщение об ошибке. Я предполагаю, что проблема может быть с log.

Error in log(names(df)[i]) : non-numeric argument to mathematical function

Мои имена переменных

> names(df)
 [1] "index"           "Year"            "barley_harv"     "barley_yield"    "cotton_harv"     "cotton_yield"   
 [7] "oat_harv"        "oat_yield"       "peanut_harv"     "peanut_yield"    "rice_harv"       "rice_yield"     
[13] "sorghum_harv"    "sorghum_yield"   "sunflower_harv"  "sunflower_yield" "AOT40"           "frez"           
[19] "dd"              "spei"            "m7"              "max.c"           "preci"           "SUM60"          
[25] "W126"            "lt"              "qt"  

Есть идеи, как решить проблему ???

Ответы [ 3 ]

1 голос
/ 02 мая 2020

Что-то вроде (фрагмент кода):

## .. outside
other_vars <- c("frez","log(dd)", "I((log(dd))^2)", 
                "preci", "I(preci^2)", 
                "m7","max.c","spei","lt","qt")
## ... inside loop ...
ff <- reformulate(c(sprintf("log(%s)",names(df)[i-1]),other_vars),
                  response=sprintf("log(%s)",names(df)[i]))
m7 <- (df 
         %>% filter(names(df)[i] > 0) 
         %>% pdata.frame(index=c("index","Year")) 
         %>% plm(formula= ff, data=., effect = c("individual"),
            model = "within") 
         ## ... coeftest stuff here
      )
0 голосов
/ 02 мая 2020

Проблема решена с помощью as.formula. См. ниже.

for(i in order) {

  m7.fl <- as.formula(paste(paste0('log(', names(df)[i], ')'), '~', paste0('log(', names(df)[i-1], ')'),'+',
                            'frez + log(dd) + I((log(dd))^2) + preci + I(preci^2) + m7 + max.c + spei + lt + qt', 
                      collapse = '+'))
  m7 <- df %>% filter(names(df)[i] > 0) %>% 
    pdata.frame(index=c("index","Year")) %>% 
    plm(formula= m7.fl, 
        data=., effect = c("individual"),model = "within") %>% 
    coeftest(., vcov = function(x) vcovHC(x, method = 'arellano', cluster = 'group', type = 'HC3'))
}

reformulate делает то же самое. В любом случае нужно указать формулу с paste. Я искал что-то более точное, то есть непосредственно использовать имена строковых переменных в формуле.

Надеюсь, другие ребята могут дать больше ссылок по этому вопросу.

0 голосов
/ 02 мая 2020

Я предполагаю, что основной проблемой c для решения здесь является Error in log(names(df)[i]) : non-numeric argument to mathematical function. Это связано с тем, что вы явно не ссылаетесь на данные, когда кодируете свой код как formula= log(names(df)[i]) ~ log(names(df)[i-1]) .... как объяснено ниже:

library(tidyverse)

# Dummy dataset
Data <- tibble(A = runif(100),
               B = runif(100))
# this works
lm(Data$B ~ Data$A) %>% broom::tidy()
# this works as well
lm(Data %>% pull(B) ~ Data %>% pull(A)) %>% broom::tidy()

# this will not work because you aren't referring to the variables within the lm() function
# but rather some random string that it does not understand
lm(names(Data)[2] ~ names(Data)[1], data = Data) %>% broom::tidy()

# A tidyeval solution for this
# Quoting your names
Name1 <- sym(names(Data)[2])
Name2 <- sym(names(Data)[1])
# Unquoting with the !! (bang bang) operator
lm(Data %>% pull(!!Name1) ~ Data %>% pull(!!Name2), data = Data) %>% broom::tidy()

Решение будет выглядеть следующим образом, хотя нет примеров данных, предоставленных для создания полного решения:

map(c(4,6,8,10,12,14,16),
    ~{
      # the first part of your code
      df <- df %>% 
        filter(names(df)[.x] > 0) %>% 
        pdata.frame(index=c("index","Year"))

      # the tidyeval solution
      Name1 <- sym(names(Data)[.x]) # Quoting
      Name2 <- sym(names(Data)[.x-1]) # Quoting

      df %>%
        plm(formula = log(pull(Data,!!Name1)) ~ log(pull(Data,!!Name2)) + # Unquoting
              frez + log(dd) + I((log(dd))^2) + preci + I(preci^2) + m7 + max.c + spei +lt + qt, 
            data= (.), 
            effect = c("individual"),
            model = "within") %>% 
        coeftest(., vcov = function(x) vcovHC(x, method = 'arellano', cluster = 'group', type = 'HC3'))
    }
)
...