1

I'm trying to reference variable names in for loop in R. For example, if I want to change each of the following variables to from numeric to a string

xtable<- tbl_df(cbind(x1=c(1,2,3), x2=c(3,4,5)))

for (varname in names(xtable)) {
 xtable$varname<- as.character(xtable$varname)
}

or rename each variable by adding an 'a' after each variable name

for (varname in names(xtable)) {
 dplyr::rename(xtable, varname = paste0(varname,'a', sep='') )
}

In general, I'm having trouble referencing the indexing variable "varname" within the for loop as the variable name it represents rather than as the word "varname".

Amazonian
  • 391
  • 2
  • 8
  • 22

2 Answers2

2

Note that tbl_df is depricated in the dplyr library. But you can use data.frame or as.data.frame easily.

xtable <- data.frame(x1=c(1,2,3), x2=c(3,4,5))
str(xtable) # shows the structure of the data.frame

R allows us to perform vector operations easily which take away the requirements for many loops.

# lapply applies a function to every column in a data.frame
xtable <- as.data.frame(lapply(xtable,as.character))
str(xtable) # shows the structure of the data.frame

# we can directly input into the names() of an object
# paste0 has a default separator of '' 
# If we put a vector into paste0 it will return a vector!
names(xtable) <- paste0(names(xtable),"a")
str(xtable)

But if you really need to reference a variable name in a loop (for a different problem)

for(varname in names(xtable)) {
  print(xtable[varname]) # xtable[varname] outputs a table with one column including header
  print(xtable[[varname]]) # xtable[[varname]] outputs only the contects of the varname vector
}
Adam Sampson
  • 1,971
  • 1
  • 7
  • 15
2

As others have mentioned, there is no need to use a for loop in both of your cases. There are two convenience functions in dplyr called mutate_all and mutate_if that will let you do the first case very easily:

library(dplyr)

# Convert all columns to character
xtable %>%
  mutate_all(as.character)

# Convert all numeric columns to character
xtable %>%
  mutate_if(is.numeric, as.character)

Result:

# A tibble: 3 x 2
     x1    x2
  <chr> <chr>
1     1     3
2     2     4
3     3     5

For second case, you can also use setNames and chain it with the first case:

xtable %>%
  mutate_all(as.character) %>%
  setNames(paste0(names(xtable), "a"))

Result:

# A tibble: 3 x 2
    x1a   x2a
  <chr> <chr>
1     1     3
2     2     4
3     3     5
acylam
  • 18,231
  • 5
  • 36
  • 45