编码右行方式-避免for循环 [英] Coding the R-ight way - avoiding the for loop

查看:122
本文介绍了编码右行方式-避免for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在检查我的.R文件之一,并通过对其进行了一些清理来尝试更加熟悉以正确的方式编写代码.作为一个初学者,我最喜欢的出发点之一是摆脱for()循环,并尝试将表达式转换为功能编程形式. 所以这是场景:

I am going through one of my .R files and by cleaning it up a little bit I am trying to get more familiar with writing the code the r-ight way. As a beginner, one of my favorite starting points is to get rid of the for() loops and try to transform the expression into a functional programming form. So here is the scenario:

我正在将一堆data.frames组装成list供以后使用.

I am assembling a bunch of data.frames into a list for later usage.

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

现在,我想看看每个data.frame的列名并替换某些字符串.例如,我喜欢用"baz"代替每个"foo"和"bar".目前,我正在使用for()循环完成工作,看起来有些尴尬.

Now I like to take a look at each data.frame's column names and substitute certain character strings. Eg I like to substitute each "foo" and "bar" with "baz". At the moment I am getting the job done with a for() loop which looks a bit awkward.

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")
  }
}

因为我在这里使用list,所以我想到了lapply函数.我尝试使用lapply函数处理该作业的所有尝试似乎都不错,但只是乍一看.如果我写

Since I am working here with a list I thought about the lapply function. My attempts handling the job with the lapply function all seem to look alright but only at first sight. If I write

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

最后一行几乎打印出我想要的内容.但是,如果我再看一看dataList中data.frames的实际名称:

the last line prints out almost what I am looking for. However, if i take another look at the actual names of the data.frames in dataList:

lapply (dataList, colnames)

我发现初始字符串没有任何更改.

I see that no changes have been made to the initial character strings.

那么我该如何重写for()循环并将其转换为功能编程形式? 如何有效地替换字符串"foo"和"bar"?由于gsub()函数仅将长度为1的字符向量作为其pattern自变量.

So how can I rewrite the for() loop and transform it into a functional programming form? And how do I substitute both strings, "foo" and "bar", in an efficient way? Since the gsub() function takes as its pattern argument only a character vector of length one.

推荐答案

您的代码几乎可以正常工作-但请记住,R创建了您修改的对象的副本(即按值传递语义).因此,您需要将新字符串显式分配给colnames,例如:

Your code almost works -- but remember that R creates copies of the objects that you modify (i.e. pass-by-value semantics). So you need to explicitly assign the new string to colnames, like so:

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)

新列表将包含带有替换名称的数据框.就替换foo和bar而言,只需在gsub的正则表达式中使用替代模式("foo | bar").

The new list will have data frames with the replaced names. In terms of replacing both foo and bar, just use an alternate pattern in the regex in gsub ("foo|bar").

请注意,顺便说一句,您不必通过索引到列表中来执行此操作-只需使用直接对列表中的元素进行操作的函数即可:

Note, by the way, that you don't have to do this by indexing into your list -- just use a function that operates on the elements of your list directly:

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

这篇关于编码右行方式-避免for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆