【问题标题】:Coding the R-ight way - avoiding the for loop以正确的方式编码 - 避免 for 循环
【发布时间】:2011-01-27 08:19:34
【问题描述】:

我正在浏览我的一个 .R 文件,通过稍微清理它,我试图更加熟悉以正确的方式编写代码。作为初学者,我最喜欢的起点之一是摆脱for() 循环并尝试将表达式转换为函数式编程形式。 所以这里是场景:

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

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

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

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 函数处理这项工作似乎都不错,但只是乍一看。如果我写

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

最后一行几乎打印出我正在寻找的内容。但是,如果我再看一下 dataList 中 data.frames 的实际名称:

lapply (dataList, colnames)

我看到初始字符串没有任何更改。

那么如何重写for() 循环并将其转换为函数式编程形式? 以及如何以有效的方式替换两个字符串“foo”和“bar”?由于 gsub() 函数将其 pattern 参数作为其参数,因此只有长度为 1 的字符向量。

【问题讨论】:

    标签: r loops


    【解决方案1】:

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

    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") 的正则表达式中使用替代模式。

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

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

    【讨论】:

    • @Leo 感谢 Leo!它工作得非常顺利。特别是第二种方法非常优雅,因为它使索引变得多余。
    猜你喜欢
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多