R-hight coding - for loop exception

I look through one of my .R files and clean it up a bit. I am trying to figure out how to write r-hight code. As a newbie, one of my favorite starting points is to get rid of for() loops and try to transform the expression into a functional programming form. So here is the scenario:

I am collecting a bunch of data.frames in list for later use.

 dataList <- list (dataA, dataB, dataC, dataD, dataE ) 

Now I like to look at the names of each column of data.frame and substitute specific lines of characters. For example, I like to replace each "foo" and "bar" with "baz". I am currently doing the work with a for() loop, which looks a bit uncomfortable.

 colnames(dataList[[1]]) [1] "foo" "code" "lp15" "bar" "lh15" colnames(dataList[[2]]) [1] "a" "code" "lp50" "ls50" "foo" matchVec <- c("foo", "bar") for (i in seq(dataList)) { for (j in seq(matchVec)) { colnames (dataList[[i]])[grep(pattern=matchVec[j], x=colnames (dataList[[i]]))] <- c("baz") } } 

Since I work here with list , I was thinking of a lapply function. My attempts to process a job using the lapply function look good, but only at first glance. If i write

 f <- function(i, xList) { gsub(pattern=c("foo"), replacement=c("baz"), x=colnames(xList[[i]])) } lapply(seq(dataList), f, xList=dataList) 

the last line prints almost what I'm looking for. However, if I look again at the actual data.frames names in the data list:

 lapply (dataList, colnames) 

I see that there were no changes to the initial character strings.

So, how can I rewrite the for() loop and convert it to a functional programming form? And how can I replace both "foo" and "bar" lines in an efficient way? Since the gsub() function accepts as the argument to pattern only a vector of characters of length one.

+4
source share
1 answer

Your code almost works - but remember that R creates copies of the objects you are modifying (i.e. pass-by-value semantics). Therefore, you need to explicitly assign a new line for colnames, for example:

 dataA <- dataB <- data.frame(matrix(1:20,ncol=5)) names(dataA) <- c("foo","code","lp15","bar","lh15") names(dataB) <- c("a","code","lp50","ls50","foo") dataList <- list(dataA, dataB) f <- function(i, xList) { colnames(xList[[i]]) <- gsub(pattern=c("foo|bar"), replacement=c("baz"), x=colnames(xList[[i]])) xList[[i]] } dataList <- lapply(seq(dataList), f, xList=dataList) 

Data frames with replaced names will be created in the new list. Regarding replacing both foo and the bar, just use the alternate regex pattern in gsub ("foo | bar").

Please note that, by the way, you do not need to do this by indexing into your list - just use a function that directly works with the elements of your list:

 f <- function(df) { colnames(df) <- gsub(pattern=c("foo|bar"), replacement=c("baz"), x=colnames(df)) df } dataList <- lapply(dataList, f) 
+9
source

Source: https://habr.com/ru/post/1304054/


All Articles