Jrakru56
Jrakru56

Reputation: 1321

Error: target of assignment expands to non-language object

I am trying to dynamically clean up some column names for a large number of tables and I get the above error.

I have a gut feeling that I should be using quo but I have no idea on how to do that.

Any ideas?

The apply_alias applies a set of business rules to clean the names.

apply_alias <-  function(l){
  which(l=="Geography")
  l[which(l=="Geography")]  <- "GEO"

  toupper(l)
}

The cleanup_column_names_tbl applies the alias_function to a list of table

cleanup_column_names_tbl <- function(PID){
  for(p in PID){
    names(get(paste0("tbl_",p))) <- apply_alias(names(get(paste0("tbl_",p))))
  }
}

cleanup_column_names_tbl("14100287")

When I try to run it i get the following error message:

> cleanup_column_names_tbl("14100287")
Error in names(get(paste0("tbl_", p))) <- apply_alias(names(get(paste0("tbl_",  : 
  target of assignment expands to non-language object

Sample data:

> dput(tbl_14100287[1,])
structure(list(V1 = 0L, REF_DATE = "1976-01", GEO = "Canada", 
    DGUID = "2016A000011124", `Labour force characteristics` = "Population", 
    Sex = "Both sexes", `Age group` = "15 years and over", Statistics = "Estimate", 
    `Data type` = "Seasonally adjusted", UOM = "Persons", UOM_ID = 249L, 
    SCALAR_FACTOR = "thousands", SCALAR_ID = 3L, VECTOR = "v2062809", 
    COORDINATE = "1.1.1.1.1.1", VALUE = 16852.4, STATUS = "", 
    SYMBOL = NA, TERMINATED = NA, DECIMALS = 1L), class = c("data.table", 
"data.frame"), row.names = c(NA, -1L), .internal.selfref = <pointer: 0x000002123cf21ef0>)

Upvotes: 1

Views: 3245

Answers (2)

Jrakru56
Jrakru56

Reputation: 1321

My solution:

Creating and expression and evaluating it. It is short but somehow does not feel like it is the proper way of doing things since I am breaking away from the functional paradigm of R.

cleanup_column_names_tbl <- function(PID){
  for(p in PID){
    expr1 <- paste0("names(", paste0("tbl_",p), ") <- apply_alias(names(", paste0("tbl_",p),"))")
    eval(rlang::parse_expr(expr1))
    }
}

Edit:

A slightly different way that:

  • avoids using strings
  • a little more flexible since it allows the use of strings and symbol
library(rlang)
test_df <- data.frame(a=1:10,b=1:10)
test_df2 <- data.frame(a=1:10,b=1:10)


fix_names <-  function(df){

  x <- ensym(df)
  expr1 <- expr(names(!!x) <- toupper(names(!!x)))
  eval(expr1, envir = parent.env(environment()))
  # expr1
}

fix_names(test_df)
fix_names("test_df2")

names(test_df)
#> [1] "A" "B"
names(test_df2)
#> [1] "A" "B"

Upvotes: 0

Rui Barradas
Rui Barradas

Reputation: 76402

You cannot assign a value to get since there is no function get<-. The right way of doing it would be something like the following.

apply_alias <-  function(l){
  l[which(l == "Geography")]  <- "GEO"
  toupper(l)
}

cleanup_column_names_tbl <- function(PID, envir = .GlobalEnv){
  pid_full <- paste0("tbl_", PID)
  res <- lapply(pid_full, function(p){
    nms <- apply_alias(names(get(p)))
    DF <- get(p)
    names(DF) <- nms
    DF
  })
  names(res) <- pid_full
  list2env(res, envir = envir)
  invisible(NULL)
}


cleanup_column_names_tbl("14100287")

names(tbl_14100287)
# [1] "V1"                           "REF_DATE"                    
# [3] "GEO"                          "DGUID"                       
# [5] "LABOUR FORCE CHARACTERISTICS" "SEX"                         
# [7] "AGE GROUP"                    "STATISTICS"                  
# [9] "DATA TYPE"                    "UOM"                         
#[11] "UOM_ID"                       "SCALAR_FACTOR"               
#[13] "SCALAR_ID"                    "VECTOR"                      
#[15] "COORDINATE"                   "VALUE"                       
#[17] "STATUS"                       "SYMBOL"                      
#[19] "TERMINATED"                   "DECIMALS"  

Upvotes: 1

Related Questions