【问题标题】:How to properly manipulate a string column in a data frame in R?如何正确操作 R 中数据框中的字符串列?
【发布时间】:2013-07-18 23:50:20
【问题描述】:

我有一个 data.frame,其中包含一个包含句点的字符串列,例如“a.b.c.X”。我想按句点拆分字符串并保留第三段,例如给出的示例中的“c”。这就是我正在做的事情。

> df = data.frame(v=c("a.b.a.X", "a.b.b.X", "a.b.c.X"), b=seq(1,3))
> df
        v b
1 a.b.a.X 1
2 a.b.b.X 2
3 a.b.c.X 3

而我想要的是

> df = data.frame(v=c("a.b.a.X", "a.b.b.X", "a.b.c.X"), b=seq(1,3))
> df
        v b
1 a 1
2 b 2
3 c 3

我正在尝试使用within,但我得到了奇怪的结果。第一列第一行的值正在重复。

> get = function(x) { unlist(strsplit(x, "\\."))[3] }
> within(df, v <- get(as.character(v)))
  v b
1 a 1
2 a 2
3 a 3

这样做的最佳做法是什么?我做错了什么?


更新: 这是我从@agstudy 的回答中使用的解决方案:

> df = data.frame(v=c("a.b.a.X", "a.b.b.X", "a.b.c.X"), b=seq(1,3))
> get = function(x) gsub(".*?[.].*?[.](.*?)[.].*", '\\1', x)
> within(df, v <- get(v))                                                                                                                                                               
  v b
1 a 1
2 b 2
3 c 3

【问题讨论】:

    标签: regex r string dataframe


    【解决方案1】:

    你可以使用一些正则表达式:

    gsub(".*?[.].*?[.](.*?)[.].*", '\\1', df$v)
    [1] "a" "b" "c"
    

    或者更简洁:

    gsub("(.*?[.]){2}(.*?)[.].*", '\\2', v)
    

    【讨论】:

    • 正则表达式总是要求我做一些思考,所以当别人做这些思考时,我很感激。 +1
    • @TylerRinker 谢谢,虽然我在这方面很懒 :)(懒惰的贪婪)
    • @agstudy 谢谢!我一直在努力寻找正确的方法来使用 R 中的正则表达式来做我想做的事情。以前我在将数据导入 R 之前先在 perl 中进行转换,但我知道必须有一种方法可以在 R 中做到这一点。所以strsplit/unlistgsub 哪个更快?
    • @drsnyder 我认为这里的gsub 更快,它是矢量化的,其他解决方案使用循环。但是您应该进行基准测试以验证这一点。
    • 如何让 gsub 在数据框内工作?我希望能够跨数据框运行一个函数并就地更新值。上面的@TylerRinker 解决方案可以正确执行此操作,但您提供的 gsub 方法没有。谢谢!
    【解决方案2】:

    问题不在于within,而在于您的get 函数。它返回一个字符 ("a"),当添加到您的 data.frame 时会被回收。您的代码应如下所示:

    get.third <- function(x) sapply(strsplit(x, "\\."), `[[`, 3)
    within(df, v <- get.third(as.character(v)))
    

    【讨论】:

    • 感谢您的快速回复。在这种情况下使用strsplit + unlistsapply 有什么区别?具体为什么get的返回值被回收而不是单独应用到数据框中的每一行?
    【解决方案3】:

    这是一种可能的解决方案:

    df[, "v"] <- do.call(rbind, strsplit(as.character(df[, "v"]), "\\."))[, 3]
    
    ## > df
    ##   v b
    ## 1 a 1
    ## 2 b 2
    ## 3 c 3
    

    【讨论】:

      【解决方案4】:

      “我做错了什么”的答案是,您认为提取每个拆分字符串的第三个元素的代码实际上是把 all 的元素放入 all 你的字符串在一个向量中,然后返回第三个元素:

      get = function(x) { 
        splits = strsplit(x, "\\.")
        print("All the elements: ")
        print(unlist(splits))
        print("The third element:")
        print(unlist(splits)[3])
        # What you actually wanted:
        third_chars = sapply(splits, function (x) x[3])
      }
      within(df, v2 <- get(as.character(v)))
      

      【讨论】:

        猜你喜欢
        • 2015-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-23
        • 1970-01-01
        • 2016-08-21
        • 1970-01-01
        相关资源
        最近更新 更多