rfilternumeric

Hamilton Filtering in R


Sort of new R user here. I'm trying to decompose GDP series into trend and cycle using Hamilton's proposed filter I'm following the neverhpfilter package (https://github.com/JustinMShea/neverhpfilter?tab=readme-ov-file#readme)

This is my set up

library(OECD)
library(tidyr)
library(neverhpfilter)
library(lubridate)
gdp_data=get_dataset("QNA")

gdp_data=gdp_data[gdp_data$SUBJECT=="B1_GS1",]

gdp_data=gdp_data[gdp_data$MEASURE=="CQR",]

gdp_data=gdp_data[gdp_data$TIME_FORMAT=="P3M",]

gdp_data=gdp_data[,c(2,5,10)]
gdp_data$ObsValue=as.numeric(gdp_data$ObsValue)
gdp_growth=gdp_data%>%
  group_by(LOCATION)%>%
  mutate(growth=log(ObsValue)-dplyr::lag(log(ObsValue)))

gdp_growth$Time=yq(gdp_growth$Time)
gdp_growth=gdp_growth[gdp_growth$Time>="1991-04-01",]
gdp_growth$LOCATION <- countrycode(gdp_growth$LOCATION, origin = "iso3c", destination = "country.name")
colnames(gdp_growth)=c("country", "gdp_value", "date", "growth")


gdp_list=split(gdp_growth, gdp_growth$country)
countries_total=names(gdp_list)
filtered_gdp=list()


for (country_j in countries_total) {
  country_temp=gdp_list[[country_j]]
  country_temp_xts=as.xts(country_temp)
  gdp_value=country_temp_xts[,c(2)]
  country_temp_hf=yth_filter(100*log(gdp_value), h=8, p=4, output=c("x", "trend", "cycle"))
  filtered_gdp[[country_j]]=country_temp_hf
  
}


I get an error saying that

Error in log(gdp_value) : non-numeric argument to mathematical function

But in the examples, the data used in the process is the same class as my data

class(country_temp_xts) [1] "xts" "zoo"


Solution

  • With library(countrycode) was able to run most of your code, which was helpful.

    I believe the error has to do with the structure of your xts object and gdp_value being character and not numeric.

    Step-by-step, I believe this is what is happening in your for block:

    You start with this (using first Country as example, Australia):

    country_j <- countries_total[1]
    country_temp=gdp_list[[country_j]] 
    

    Then str(country_temp) would be:

    'data.frame':   130 obs. of  4 variables:
     $ country  : chr  "Australia" "Australia" "Australia" "Australia" ...
     $ gdp_value: num  102357 104041 110785 102777 105668 ...
     $ date     : Date, format: "1991-04-01" "1991-07-01" "1991-10-01" "1992-01-01" ...
     $ growth   : num  0.0288 0.0163 0.0628 -0.075 0.0277 ...
    

    You will see that the data.frame includes the date, numeric gdp_value and growth, and character value of country (a mix of different types).

    When you convert to xts object:

    country_temp_xts=as.xts(country_temp)
    

    You have with str(country_temp_xts):

    An xts object on 1991-04-01 / 2023-07-01 containing: 
      Data:    character [130, 3]
      Columns: country, gdp_value, growth
      Index:   Date [130] (TZ: "UTC")
    

    Note this has Data as character, not numeric. This is because these objects are matrices with ordered index attribute. You cannot mix types, which you can with a data.frame. If one column is character, then all will become character (similar to matrices).

    One option is to select your gdp_value which is the only value you are using, excluding the other character column, and then convert to xts object:

    country_temp_xts <- as.xts(country_temp[, c("date", "gdp_value")])
    

    Another approach, assuming you had a single character column, which you'd want to be numeric, is to use:

    storage.mode(<name_of_xts_object>) <- "numeric"
    

    Let me know if this addresses your issue.