【问题标题】:R: Recursive *ply/plyr function; for loop replacementR:递归 *ply/plyr 函数; for循环替换
【发布时间】:2014-06-25 18:37:24
【问题描述】:

我正在尝试用 *ply 类型函数替换 for 循环。

我遇到的问题是我不确定如何重复更新相同的数据。

这是一些示例数据(我知道这个具体示例可以通过其他方式完成,但这只是为了简单起见——我的实际示例要复杂得多):

sample_pat_rep <-  data.frame(matrix(NA, ncol=2, nrow=3, dimnames=list(c(), c("Pattern","Replacement"))), stringsAsFactors=FALSE)
sample_pat_rep[1,] <-  c("a","A")
sample_pat_rep[2,] <-  c("b","B")
sample_pat_rep[3,] <-  c("c","C")

sample_strings <-  data.frame(matrix(NA, ncol=2, nrow=3, dimnames=list(c(), c("Original","Fixed"))), stringsAsFactors=FALSE)
sample_strings[1,] <-  c("aaaaaaaa bbbbbbbb cccccccc","aaaaaaaa bbbbbbbb cccccccc")
sample_strings[2,] <-  c("aAaAaAaA bBbBbBbB cCcCcCcC","aAaAaAaA bBbBbBbB cCcCcCcC")
sample_strings[3,] <-  c("AaAaAaAa BbBbBbBb CcCcCcCc","AaAaAaAa BbBbBbBb CcCcCcCc")

这是一个 for 循环版本:

sample_strings1 <- sample_strings
for (i in 1:nrow(sample_pat_rep))
{
  sample_strings1[,c("Fixed")] <- gsub(sample_pat_rep[i,c("Pattern")], sample_pat_rep[i,c("Replacement")], sample_strings1[,c("Fixed")],ignore.case = TRUE)
} 

当我尝试使用 adply 复制它时,它不会更新数据——它必须复制并重新绑定它。

sample_strings2 <- adply(.data=sample_pat_rep, .margins=1, .fun = function(x,data){

data[,c("Fixed")] <- gsub(x[,c("Pattern")], x[,c("Replacement")], data[,c("Fixed")],ignore.case = TRUE)
return(data)

}, data=sample_strings, .expand = FALSE, .progress = "none", .inform = FALSE, .parallel = FALSE, .paropts = NULL)

我确信有一个简单的解决方法。我查看了 Rapply,但不清楚这是否是解决方法。

也许写一个函数来调用??使用 Rapply??

提前谢谢!


更新:新数据

这更接近实际情况。匹配是动态的并且基于外部系统。我试图避免过于复杂的正则表达式或嵌套 if elses。

library(plyr)

sample_match <-  data.frame(matrix(NA, ncol=1, nrow=3, dimnames=list(c(), c("Match"))), stringsAsFactors=FALSE)
sample_match[1,] <-  c("dog")
sample_match[2,] <-  c("cat")
sample_match[3,] <-  c("bear")

sample_strings <-  data.frame(matrix(NA, ncol=2, nrow=3, dimnames=list(c(), c("Sentence","Has_Animal"))), stringsAsFactors=FALSE)
sample_strings[1,] <-  c("This person only has a cat",0)
sample_strings[2,] <-  c("This person has a cat and a dog",0)
sample_strings[3,] <-  c("This person has no animals",0)

sample_strings1 <- sample_strings
for (i in 1:nrow(sample_match))
{
 sample_strings1[,c("Has_Animal")] <- ifelse(grepl(sample_match[i,c("Match")], sample_strings1[,c("Sentence")]), 1,sample_strings1[,c("Has_Animal")])
} 


sample_strings2 <- adply(.data=sample_match, .margins=1, .fun = function(x,data){

 data[,c("Has_Animal")] <- ifelse(grepl(x[,c("Match")], data[,c("Sentence")]), 1,data[,c("Has_Animal")])
 return(data)

}, data=sample_strings, .expand = FALSE, .progress = "none", .inform = FALSE, .parallel = FALSE, .paropts = NULL)

【问题讨论】:

  • 忍不住问:你不能用toupper()
  • 这个例子我可以,但我的真实案例与 gsub 没有任何关系。这只是我想到的第一件事。
  • 和gsub也没有关系吧?嗯。你能给我们一个实际问题的例子吗?

标签: r recursion plyr apply


【解决方案1】:

这是直接plyr 的问题方法:

ddply(sample_strings,.(Sentence),function(x,ref = sample_match) {
  any(unlist(strsplit(x[["Sentence"]]," ")) %in% ref[[1]])
  })

                         Sentence    V1
1 This person has a cat and a dog  TRUE
2      This person has no animals FALSE
3      This person only has a cat  TRUE

【讨论】:

  • 谢谢安德鲁。我真的很感激。
【解决方案2】:

更新:误解了问题,sample_strings2 是必需的结果。更新了现在给出sample_strings1 的答案,IIUC 是必需的。

这是使用base的解决方案:

pattern = paste(sample_match$Match, collapse="|")
transform(sample_strings, Has_Animal = grepl(pattern, Sentence)*1L)

#                          Sentence Has_Animal
# 1      This person only has a cat          1
# 2 This person has a cat and a dog          1
# 3      This person has no animals          0

如果您不想匹配其中包含该模式的单词,例如:concatenate 包含 cat,那么您可以使用正则表达式 \b 作为单词边界。

pattern = paste(paste("\\b", sample_match$Match, "\\b", sep=""), collapse="|")
grepl(pattern, c("cat", "concatenate"))
# [1] TRUE FALSE

【讨论】:

  • Arun,我很欣赏这一点,但这与我的 adply 函数的作用相同。我正在寻找一个 3 行的最终数据集,这三个正在更新,而不是每次附加的三行。例如,for 循环的答案有 3 行。
  • 谢谢阿伦。这真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
相关资源
最近更新 更多