【问题标题】:Referencing Elements in Nested for loops in R在 R 中的嵌套 for 循环中引用元素
【发布时间】:2017-07-18 14:48:02
【问题描述】:

我正在尝试编写一个循环来对数据框执行以下操作:

对于“名称”列中的每个名称,检查“推荐”列中是否存在粗略匹配(通过 agrep() 完成)。如果存在匹配项,请将“推荐”列中与名称大致匹配的所有单元格替换为“推荐”。

到目前为止,这是我的代码:

for (i in 1:1000){
 for (q in 1:length(agrep(c$Name[i], c$Referal))){
  if (length(agrep(c$Name[i], c$Referal)>0)){
   c$Referal[agrep(c$Name[i], c$Referal)[q]]<-'panda'
  }
 }
}

但是,此代码(在运行 20 分钟后)将“推荐”列中的所有单元格替换为“推荐”。我想知道第一行中的“i”在整个循环中是否保持不变?显然是一个笨重的代码块,但我想不出它为什么会这样做......

一个例子是:

Name <- c('michael jordan', 'carrot', 'ginger')
Referral <-('internet', 'facebook', 'mike jordan')
df <- data.frame(Name, Referral)

运行函数后,理想情况下 df$Referral[3]=='referral' 为 TRUE。

【问题讨论】:

  • 请分享您的数据框和所需输出的可重现示例。您可以使用其他方法来替换for loop 操作。但我们需要了解您的数据才能提供帮助。
  • 您可以参考此链接了解如何制作可重现的示例:stackoverflow.com/questions/5963269/…
  • 谢谢——我会努力让数据集的一部分重现错误

标签: r for-loop if-statement agrep


【解决方案1】:

不确定agrep 是否会以您期望的方式为您服务:

agrep('michael jordan', 'mike jordan')
integer(0)

所以我稍微改变了你的数据。 mike jordan 现在在两个向量中:

Name <- c('mike jordan', 'carrot', 'ginger')
Referral <-c('internet', 'facebook', 'mike jordan')

我还将逻辑条件更改为Referral[x] %in% Name。然后就可以了

library(tidyverse)
newReferral <- map_chr(Referral, ~ifelse(.x %in% Name,'referral', .x))

[1] "internet" "facebook" "referral"

【讨论】:

  • 谢谢!! tidyverse 功能令人难以置信。当我的原始代码成功时,数据框中每 500 行大约需要 1 分钟。这在大约 4 秒内对所有 11,000 行运行。非常感谢。
  • 很高兴为您提供帮助。您可以通过接受答案来结束此问题。如果之后出现更好的答案,您也可以重新接受新的答案。
【解决方案2】:

您是否尝试过使用value=TRUE 选项?

按原样,您的代码从agrep() 返回整个向量。使用value=TRUE 应该只返回匹配的对象。

编辑:这里有一些代码可帮助您了解 agrep() 返回的内容以及它在循环中的工作方式。

Name <- c('michael jordan', 'carrot', 'ginger')
Referral <- c('internet', 'facebook', 'mike jordan')
df <- data.frame(Name, Referral)    

agrep(df$Name[1], df$Referral, max = 5, value = TRUE)

# [1] "mike jordan"

length(agrep(df$Name[1], df$Referral, max = 5, value = TRUE))

# [1] 1

agrep(df$Name[1], df$Referral, max.distance = 0.5)

# integer(0)

df$Referral[agrep(df$Name[1], df$Referral)[1]]

# NULL

for (i in 1:3){
  for (q in 1:length(agrep(df$Name[i], df$Referral))){
    if (length(agrep(df$Name[i], df$Referral)>0)){
      df$Referral[agrep(df$Name[i], df$Referral)[q]] <-'panda'
    }
  }
}

只是为了更清楚地说明max 参数的重要性。这里有 3 个示例,请记住 integer(0) 在 R 中是一个零长度向量。

> agrep(df$Name[1], df$Referral) 
integer(0) 
> agrep(df$Name[1], df$Referral, max.distance = 0.2) 
integer(0) 
> agrep(df$Name[1], df$Referral, max.distance = 0.5) 
[1] 3 

【讨论】:

  • 你会在哪里插入 value=TRUE 参数?在所有行中?
  • 哦,我明白你在说什么了。你建议我返回一个我目前有一个索引的值——我现在的解决方案是使用“q”通过第二行中的索引引用该值。这绝对是效率的提高,谢谢。我仍然想知道为什么更长的方法行不通!
  • 您还没有设置maxdistanceagrep() 使用 Levenshtein 距离来找到匹配两个单词所需的最小转换次数。默认值为max.distance = 0.1,这意味着任何超过目标模式10% 的内容都不会被匹配。
  • 感谢您将其分解。你能解释一下为什么agrep(df$Name[1], df$Referral) 没有看到 Name[1] 和 Referral[3] 之间的相似性,但是当你使用整列 Names 作为搜索模式(例如agrep(df$Name, df$Referral, max = 5, value = TRUE))时成功找到了相同的相似性?
猜你喜欢
  • 1970-01-01
  • 2023-03-02
  • 1970-01-01
  • 2017-04-30
  • 2021-12-01
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 2016-08-25
相关资源
最近更新 更多