【问题标题】:Dplyr pipe (%>%) within mutate()?mutate()中的Dplyr管道(%>%)?
【发布时间】:2016-09-02 14:37:19
【问题描述】:

dplyr 中的管道很酷,有时我想通过对其应用多个命令来清理一列。有没有办法在mutate() 命令中使用管道?我在使用正则表达式时最注意到这一点,并且在其他情况下也会出现。在下面的示例中,我可以清楚地看到我对“清洁”列应用的不同操作,我很好奇是否有一种方法可以在 mutate() 中模仿 %>%

library(dplyr)
phone <- data.frame(Numbers = c("1234567890", "555-3456789", "222-222-2222",   
                                "5131831249", "123.321.1234","(333)444-5555",
                                "+1 123-223-3234", "555-666-7777 x100"), 
                                stringsAsFactors = F)

phone2 <- phone %>%
          mutate(Clean = gsub("[A-Za-z].*", "", Numbers), #remove extensions
                 Clean = gsub("[^0-9]", "", Clean),       #remove parentheses, dashes, etc
                 Clean = substr(Clean, nchar(Clean)-9, nchar(Clean)), #grab the right 10 characters
                 Clean = gsub("(^\\d{3})(\\d{3})(\\d{4}$)", "(\\1)\\2-\\3", Clean)) #format

phone2

我知道可能有更好的gsub() 命令,但就这个问题而言,我想知道是否有办法将这些gsub() 元素连接在一起,这样我就不必继续写@ 987654328@ 但也不必使用我将它们相互嵌入的方法。

如果你用一个更简单的例子回答这个问题,我会很好。

【问题讨论】:

  • 使用.,yake。也可以重新定义gsub2 &lt;- function(x, ...) gsub(x = x, ...),这样你就可以做到data %&gt;% gsub2('pat', 'repl') %&gt;% gsub2('...','etc')

标签: r dplyr


【解决方案1】:

不要落入无尽管道的陷阱。为了可读性和效率做正确的事,写一个函数。

phone %>% mutate(Clean = cleanPhone(Numbers))
#             Numbers         Clean
# 1        1234567890 (123)456-7890
# 2       555-3456789 (555)345-6789
# 3      222-222-2222 (222)222-2222
# 4        5131831249 (513)183-1249
# 5      123.321.1234 (123)321-1234
# 6     (333)444-5555 (333)444-5555
# 7   +1 123-223-3234 (123)223-3234
# 8 555-666-7777 x100 (666)777-7100

自定义函数:

cleanPhone <- function(x) {
  x2 <- gsub("[^0-9]", "", x)
  x3 <- substr(x2, nchar(x2)-9, nchar(x2))
  gsub("(^\\d{3})(\\d{3})(\\d{4}$)", "(\\1)\\2-\\3", x3)
}

【讨论】:

  • 好的,这个答案赢得了可读性,我同意你的观点。但是,我将解决方案提供给 @akrun,因为它显示了我正在寻找的答案。
  • 学习函数式编程将使您受益于任何特定的管道任务。
【解决方案2】:

我猜你需要

phone %>% 
     mutate(Clean = gsub("[A-Za-z].*", "", Numbers) %>%
                    gsub("[^0-9]", "", .) %>%
                    substr(., nchar(.)-9, nchar(.)) %>% 
                    gsub("(^\\d{3})(\\d{3})(\\d{4}$)", "(\\1)\\2-\\3", .))
#            Numbers         Clean
#1        1234567890 (123)456-7890
#2       555-3456789 (555)345-6789
#3      222-222-2222 (222)222-2222
#4        5131831249 (513)183-1249
#5      123.321.1234 (123)321-1234
#6     (333)444-5555 (333)444-5555
#7   +1 123-223-3234 (123)223-3234
#8 555-666-7777 x100 (555)666-7777

【讨论】:

  • 啊,我总是对懒惰的点感到困惑
【解决方案3】:

即使问题得到了解答,请考虑使用 magrittr 代替 dplyr 的方法

require(magrittr)
phone <- data.frame(Numbers = c("1234567890", "555-3456789", "222-222-2222",   
                                "5131831249", "123.321.1234","(333)444-5555",
                                "+1 123-223-3234", "555-666-7777 x100"), 
                                stringsAsFactors = F)
phone

cleanchain<-  phone$Numbers %>%  gsub("[A-Za-z].*", "", .) %>% gsub("[^0-9]", "", .) %>% substr(., nchar(.)-9, nchar(.)) %>% gsub("(^\\d{3})(\\d{3})(\\d{4}$)", "(\\1)\\2-\\3", .) 

cleanchain  

data.frame(old=phone$Numbers,new=cleanchain, stringsAsFactors = F)

【讨论】:

    猜你喜欢
    • 2018-05-17
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 2017-08-08
    • 2016-10-15
    • 2015-05-02
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多