【问题标题】:Applying multiple function via sapply通过 sapply 应用多个功能
【发布时间】:2016-02-02 10:19:29
【问题描述】:

我正在尝试在R-Bloggers 上发布的sapply 中复制有关应用多个功能的解决方案,但我无法让它以所需的方式工作。我正在使用一个简单的数据集,类似于下面生成的数据集:

require(datasets)
crs_mat <- cor(mtcars)

# Triangle function
get_upper_tri <- function(cormat){
  cormat[lower.tri(cormat)] <- NA
  return(cormat)
}

require(reshape2)
crs_mat <- melt(get_upper_tri(crs_mat))

我想在 Var1Var2 列之间替换一些文本值。下面的 错误 语法说明了我想要实现的目标:

crs_mat[,1:2] <- sapply(crs_mat[,1:2], function(x) {
 # Replace first phrase
 gsub("mpg","MPG",x), 
 # Replace second phrase
  gsub("gear", "GeArr",x)
 # Ideally, perform other changes
})

当然,代码在语法上不正确并且会失败。总而言之,我想做以下事情:

  1. 遍历前两列中的所有值(Var1 和 Var2) 并通过gsub 执行简单替换。
  2. 理想情况下,我想避免定义单独的函数,如 linked 帖子中所讨论的那样,并将所有内容sapply 语法中
  3. 我不想要嵌套循环

我查看了herehere 讨论的大致相似的主题,但如果可能的话,我想避免使用plyr。我也有兴趣替换列值而不是创建新列,并且我想避免指定任何列名。在使用我现有的数据框时,使用列号对我来说更方便。

编辑

在非常有用的 cmets 之后,我想要实现的目标可以总结在下面的解决方案中:

fun.clean.columns <- function(x, str_width = 15) {
  # Make character
  x <- as.character(x)
  # Replace various phrases
  x <- gsub("perc85","something else", x)
  x <- gsub("again", x)
  x <- gsub("more","even more", x)
  x <- gsub("abc","ohmg", x)
  # Clean spaces
  x <- trimws(x)
  # Wrap strings
  x <- str_wrap(x, width = str_width)
  # Return object
  return(x)
}
mean_data[,1:2] <- sapply(mean_data[,1:2], fun.clean.columns)

我的global.env 中不需要此函数,因此我可以在此之后运行rm,但更好的解决方案将涉及在apply 语法中挤压它。

【问题讨论】:

  • 你能详细说明你想做的其他改变吗?你有多少替代品?
  • @Heroka,感谢您的关注。假设我愿意进行 10 次替换和其他外观更改,例如应用 trimws。原则上,gsub 对我来说已经足够了,但我希望能够将gsub 命令的各种迭代应用到我决定通过sapply 传递的列。
  • 您遇到的主要问题是您没有分配任何内容,因此没有进行任何更改。
  • 如果要替换多个条目,为什么不使用mgsub from library(qdap)
  • @Heroka 我知道,如前所述,代码是错误的,但它传达了我想要实现的目标。简而言之,我想将多个操作应用于没有 within sapply 的列列表。实际上,这是一个语法问题。我可以编写一个函数并将其传递给sapply,但我不想这样做。

标签: r function apply gsub sapply


【解决方案1】:

我们可以使用library(qdap) 中的mgsub 来替换多个模式。在这里,我使用lapply 循环第一列和第二列,并将结果分配回crs_mat[,1:2]。请注意,我使用的是lapply 而不是sapply,因为lapply 保持结构完整

library(qdap)
crs_mat[,1:2] <- lapply(crs_mat[,1:2], mgsub, 
   pattern=c('mpg', 'gear'), replacement=c('MPG', 'GeArr'))

【讨论】:

  • 非常感谢您的贡献。该解决方案在gsub 的情况下肯定会起作用,我最感兴趣的是扩展sapply 语法,因为我想利用可用的灵活性。例如,我可能必须申请 gsub 5 次,在 trimws 之后,最后是 toupper 或这些行。
  • @Konrad 我猜你已经看过发布的例子,显示lapply vs sapply
  • 我做了,但我不清楚是否可以起草一个足够的语法。我知道我可以定义一个新函数my_problematic_strings &lt;- function(string_var) { # All the stuff I want to do },然后传递它:sapply(dta_with_columns, function(x) my_problematic_strings)。理想情况下,我不想定义这个函数,因为它会无缘无故地“坐在”全球环境中。
  • @Konrad 我不明白sapply 将如何比lapply 根据你提到的更好的选择。
【解决方案2】:

这是您的解决方案的开始,我认为您有能力自己扩展它。可能有更优雅的方法可用,但我没有看到它们。

crs_mat[,1:2] <- sapply(crs_mat[,1:2], function(x) {
  # Replace first phrase
  step1 <- gsub("mpg","MPG",x)
  # Replace second phrase. Note that this operates on a modified dataframe. 
  step2 <- gsub("gear", "GeArr",step1)
  # Ideally, perform other changes
  return(step2)

  #or one nested line, not practical if more needs to be done
  #return(gsub("gear", "GeArr",gsub("mpg","MPG",x)))
})

【讨论】:

  • 谢谢,这是一个开始。
猜你喜欢
  • 2023-03-31
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
相关资源
最近更新 更多