【问题标题】:how to properly loop from an external list to use inside mutate in dplyr如何从外部列表正确循环以在 dplyr 中使用内部 mutate
【发布时间】:2019-11-25 19:40:57
【问题描述】:

我正在尝试修复部分循环函数

我创建了包含字符串和正则表达式的长列表(例如“ee”)。结构如下

ee

注意:我故意将正则表达式放在那里

我想取这个列表的每个元素,并在相当大的数据框中用“BB00”替换(小部分在下面,有用的列是“c”)

dput(df)
structure(list(a = c(1, 2, 3, 4, 6, 7, 8), b = c(2011, 2012, 2010, 1995, 1998, 2011, 2011), c = c("enemy ID9", "John potassium", "chloride misch", "malchloride", "retardfalling", "friendretard", "use to beID10")), row.names = c(NA, -7L), class = "data.frame")

所以我尝试创建一个函数,它接受一个列表,并通过将每个元素传递给 dplyr 的 mutate() 中的 gsub() 来循环,如下所示

library(tibble)
library(dplyr) library(tidytext) library(tidyr)


strpDetach<- function(x){
  for(j in x){
    df1=df %>% mutate(c = gsub(j, "BB00", c,ignore.case=TRUE))
    return(df1) }
  }

df2=strpDetach(ee)

dput(df2)
structure(list(a = c(1, 2, 3, 4, 6, 7, 8), b = c(2011, 2012, 2010, 1995, 1998, 2011, 2011), c = c("enemy ID9", "John potassium", "chloride misch", "malchloride", "retardfalling", "friendBB00", "use to beID10")), row.names = c(NA, -7L), class = "data.frame")

显然,只有列表中的第一个元素有效

用另一种方式修改函数(直接取列表的每个元素)如下:

strpDetach<- function(j){df %>% mutate(c = gsub(j, "BB00", c,ignore.case=TRUE))}
for( j in ee){
      for (i in 1:ncol(df)) { 
             c=df[,3]
              df1=strpDetach(j)
          }
  }

dput(df1)
structure(list(a = c(1, 2, 3, 4, 6, 7, 8), b = c(2011, 2012, 2010, 1995, 1998, 2011, 2011), c = c("enemy ID9", "John potassium", "chloride misch", "malBB000", "retardfalling", "friendretard", "use to beID10")), row.names = c(NA, -7L), class = "data.frame")

只有列表中的最后一个元素有效

我的问题是我在循环中哪里做错了?

非常感谢您阅读我的长文!!

预期的输出是:

dput(df1)
structure(list(a = c(1, 2, 3, 4, 6, 7, 8), b = c(2011, 2012, 2010, 1995, 1998, 2011, 2011), c = c("enemy BB000", "JohnBB000", "chloride misch", "malBB000", "retardfalling", "friendBB000", "use to beBB000")), row.names = c(NA, -7L), class = "data.frame")

【问题讨论】:

  • 谢谢@akrun 我已经添加了
  • 我在下面发布了一个解决方案

标签: r for-loop dplyr


【解决方案1】:

这里,我们只需要一个循环而不是嵌套循环,因为 sub 中的 x 是矢量化的

ee <- c('ID\\d+$', 'potassium$', 'chloride$', 'retard$')
for(pat in ee) df$c <- sub(pat, "BB000", df$c)

由于替换在每个元素中发生一次,即在字符串的末尾 ($),我们只需要 subgsub- 全局替换)。除此之外,更改的列会在每个循环中更新,以便在每次运行中更新


另外,由于问题是关于dplyr,我们可以更新每个for循环中的数据集

library(dplyr)
for(pat in ee) {

    df <- df %>%
             mutate(c = str_replace(c, pat, "BB000"))
  }

【讨论】:

  • 非常感谢@akrun,第一个,在单个循环上使用'sub'就可以了。第二,在 for 循环中使用 dplyr 仅对列表中的最后一个元素执行,就像我的帖子一样,(我假设 'str_replace' 与 stringr 中的相同)
  • 我也找不到点击这个作为答案的方法。第一部分做同样的工作!!!
【解决方案2】:

我们可以通过使用正则表达式符号| 转换为or 来完成此操作而无需r 样式循环。

我不知道您的正则表达式是否符合您的意思。 "retard+$" 表示 retard 带有一个或多个 d,然后是字符串的结尾。所以retarddddd 会匹配但retardfalling 不会匹配。

# combine all the regex checks by collapsing them into a single string with a pipe in-between.
ee2 <- paste0(ee,collapse = "|")
df4 <- df %>%
  mutate(c = stringr::str_replace_all(c,ee2,"BB00"))

#a    b              c
#1 2011      enemy ID9
#2 2012      John BB00
#3 2010 chloride misch
#4 1995        malBB00
#6 1998  retardfalling
#7 2011     friendBB00
#8 2011  use to beID10

【讨论】:

  • string_replace_all 是我习惯和熟悉的。相同的正则表达式应该在 sub 中工作,但我并不总是记得如何对 sub 和 grep 进行向量输入,所以我没有在这里尝试。
  • 非常感谢@Adam Sampson。合并变异的绝佳方式。我最初使用管道,后来使用 str_replace,但从未想过合并 mutate。谢谢 。正则表达式是故意存在的
猜你喜欢
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2016-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
相关资源
最近更新 更多