【问题标题】:Filling in data frame column using regular expressions (?)使用正则表达式(?)填充数据框列
【发布时间】:2016-10-04 04:47:37
【问题描述】:

好的,所以我有一个网络论坛 cmets 的数据框。每行都有一个包含 ID 的单元格,该 ID 是该评论的父评论链接的一部分。这些行包含评论的完整永久链接,其中 ID 是变化的部分。

我想添加一列,显示附加到该父评论的用户名。我假设我需要使用一些正则表达式函数,此时我觉得这很神秘。

在工作流术语中,我需要找到其 URL 包含父评论 ID 的行,从该行中获取用户名。这是一个玩具示例:

toy <- rbind(c("yes?", "john", "www.website.com/4908", "3214", NA), c("don't think so", "mary", "www.website.com/3958", "4908", NA))
toy <- as.data.frame(toy)
colnames(toy) <- c("comment", "user", "URL", "parent", "parent_user")

         comment user                  URL parent parent_user
1           yes? john www.website.com/4908   3214        <NA>
2 don't think so mary www.website.com/3958   4908        <NA>

需要变成:

         comment user                  URL parent parent_user
1           yes? john www.website.com/4908   3214        <NA>
2 don't think so mary www.website.com/3958   4908        john

此列中的某些值将是 NA,因为它们是顶级 cmets。比如,

dataframe$parent_user <- dataframe['the row where parent
ID i is found in the URL column', 'the user name column in that row']

谢谢!!

【问题讨论】:

    标签: regex r dataframe


    【解决方案1】:

    另一个选项,使用基础 R 中的 basename 函数,“删除所有路径,包括最后一个路径分隔符(如果有)

    toy$user[match(toy$parent, basename(as.character(toy$URL)))]
    #1] <NA> john
    #Levels: john mary
    

    【讨论】:

    • basename() 在这种情况下是一个很好的函数。我从 base R 中发现了一些新东西。谢谢。 :)
    • @jazzurro - 别忘了它的表弟 - ?dirname 或者 :-)
    • 是的,我也检查过了。谢谢你。 :-)
    【解决方案2】:

    这是一个带有stri_extractmatch 的矢量化选项

    library(stringi)
    toy$parent_user <- toy$user[match(toy$parent,stri_extract(toy$URL, 
                regex=paste(toy$parent, collapse="|")))]
    toy
    #         comment user                  URL parent parent_user
    #1           yes? john www.website.com/4908   3214        <NA>
    #2 don't think so mary www.website.com/3958   4908        john
    

    或者正如@jazzurro 提到的,更快的选择是将stri_extractdata.tablefmatch 一起使用

    library(data.table)
    library(fastmatch)
    setDT(toy)[, parent_user := user[fmatch(parent, 
                      stri_extract_last_regex(str=URL, pattern = "\\d+"))]]
    

    或者base R 选项将是

    with(toy, user[match(parent, sub("\\D+", "", URL))])
    #[1] <NA> john
    #Levels: john mary
    
    nchar('with(toy, user[match(parent, sub("\\D+", "", URL))])')
    #[1] 51
    
    nchar('toy$user[match(toy$parent, basename(as.character(toy$URL)))]')
    #[1] 60
    

    【讨论】:

    • 在类似的行中,我有setDT(toy)[, parent_user := user[match(parent, stri_extract_last_regex(str = URL, pattern = "\\d+"))]]
    • 如果您的域名中有数字,这将失败 - 例如。例如www.and1.com.au
    • @thelatemail 如果 parentID 是 1 并且 OP 想要从 and1 中提取 1,那么您发布的方法也应该失败,即 basename("www.and1.com.au") #[1] "www.and1.com.au"
    • 我并不是建议他们要从 and1 中提取 1,只是 D+ 会混淆域和斜线后的 ID。
    • @thelatemail 是的,不知道parent id是否出现在最后。
    【解决方案3】:

    也许不是最漂亮的方法,而是一种选择:

    toy$parent_user <- sapply(toy$parent, 
                              function(x){p <- toy[x == sub('[^0-9]*', '', toy$URL), 'user'];
                                          ifelse(length(p) > 0, as.character(p), NA)})
    
    toy
    #          comment user                  URL parent parent_user
    # 1           yes? john www.website.com/4908   3214        <NA>
    # 2 don't think so mary www.website.com/3958   4908        john
    

    第二行实际上只是处理缺少匹配的情况。

    【讨论】:

    • 是的,看不到完全矢量化的方法......来自stringrstr_extract() 可能看起来有点干净,但不是很明显。很好的解决方案。
    • 哦,结合 akrun 的方法和我的方法得到了 toy[match(toy$parent, sub('[^0-9]*', '', toy$URL)), 'user'],这实际上相当不错,尽管我只能获得部分功劳。
    • @thelatemail 哦,我没想到在 URL 上使用 basename!我一直在寻找解析元素的函数,但我只能找到xml2::url_relative
    猜你喜欢
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2013-05-25
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多