【问题标题】:Creating a column from another columns text only仅从其他列文本创建列
【发布时间】:2014-07-24 22:14:17
【问题描述】:

我在 R 中有一个数据框,其中包含包含字母和数字的列。字母和数字的数量各不相同,因此解析将非常困难。我想做的只是创建一个仅包含来自包含字母和数字的列中的字母的列。典型的观察结果类似于 ABS98 或 GD798。

谢谢

【问题讨论】:

  • 简单的文本替换能做到吗 - gsub("[0-9]","",dat$col1) ?

标签: r string replace


【解决方案1】:

一种方法是通过gsub() 使用正则表达式。使用类似于您的数据的东西:

df <- data.frame(Ind = rep(c("ABS98","GD798"), each = 5), Dat = rnorm(10))

一个可能的正则表达式是:

with(df, gsub("[[:digit:]]", "", Ind))

其中"[[:digit:]]" 匹配您的语言环境中为数字传递的任何内容,并将这些位替换为空字符串""。这给了我们:

> with(df, gsub("[[:digit:]]", "", Ind))
 [1] "ABS" "ABS" "ABS" "ABS" "ABS" "GD"  "GD"  "GD"  "GD"  "GD"

要将其添加为列,请覆盖Ind

df2 <- transform(df, Ind = gsub("[[:digit:]]", "", Ind))

> head(df2)
  Ind        Dat
1 ABS  0.3685773
2 ABS  0.1186962
3 ABS -0.1049685
4 ABS -0.2448743
5 ABS -0.1896105
6  GD  0.8206612

或添加一个新的

df3 <- transform(df, Ind2 = gsub("[[:digit:]]", "", Ind))

> head(df3)
    Ind        Dat Ind2
1 ABS98  0.3685773  ABS
2 ABS98  0.1186962  ABS
3 ABS98 -0.1049685  ABS
4 ABS98 -0.2448743  ABS
5 ABS98 -0.1896105  ABS
6 GD798  0.8206612   GD

取决于哪个最适合您的用例。

【讨论】:

  • @thelatemail 评论有什么本质上的不同,为什么你需要*?在哪些情况下with(df, gsub("[[:digit:]]", "", Ind)) 不起作用?
  • @DavidArenburg 不是,但当我开始写这篇文章时,没有任何回应(但我分心了,花了一段时间才完成)。改进该评论的唯一方法是我试图解释正则表达式 提供了两个用于替换或添加新列的选项。不需要*;我正在尝试一个使用反向引用作为替换的示例,我似乎需要一个 * 并且在粘贴更简单的正则表达式时没有将其删除。
  • @DavidArenburg,有什么问题?那个Gavin劫持了Thela的答案?如果 Thela 想发布答案,那就已经完成了。我个人更喜欢答案空间中的答案,而不是 cmets。那是重复的吗?找到骗子,其他人肯定会很感激,但请注意,并非所有重复项都必须关闭。
  • @AnandaMahto,我没有指责 Gavin 劫持了答案,所以请不要代表我发布民粹主义 cmets。我所说的只是我看不出这与 Thelas 评论之间的显着差异,我认为它可能只是“或gsub("[[:digit:]]","",dat$col1)”的另一条评论。但现在他解释了,这似乎是合法的。
  • @DavidArenburg ?"regular expression" 建议 [foo-bar] 字符类,无论是用于数字还是其他字符都不一定是可移植的 - 所以 [:digit:] 类可以被视为比 [0-9] 更具防御性的选择以防更简单的[0-9] 在某个系统上的某个地方失败。当我看到像上面的@thelatemail 那样的 cmets 时,我认为他们没有时间充实答案,如果我有时间(在这种情况下,我对正则表达式并不熟悉,所以它是对我来说也是一个复习),然后我会添加一个答案,即使它重复了评论
【解决方案2】:

gsub 运行良好。使用它去除所有数字并将结果放在 col2 (或任何您的目标字段)中。

df=data.frame(col1=c("ABS98", "GD798", "45j9s"))
df$col2=gsub("[0-9]","",df$col1)

【讨论】:

    【解决方案3】:

    使用stringi包中的stri_replace_charclass函数:

    stri_replace_all_charclass(c("AB89","DB12"),"\\p{N}","")
    ## [1] "AB" "DB"
    

    第一个参数是要修改的向量,第二个是字符类(在本例中是 N - 数字),第三个是替换 - 一个空字符串。

    x <- stri_rand_strings(1000,10,c("[A-Z]","[0-9]"))
    x[1:6]
    ## [1] "OGYLERNWUV" "2397448180" "DPQWSDODVD" "4176825763" "GEFNQMIXMO" "7178890572" 
    microbenchmark(stri_replace_all_charclass(x,"\\p{N}",""), gsub("[0-9]","",x,perl =  TRUE), gsub("[0-9]","",x))
    Unit: microseconds
                                              expr      min        lq    median        uq      max neval
     stri_replace_all_charclass(x, "\\\\p{N}", "")  385.002  398.2755  405.5475  415.9865  603.859   100
                 gsub("[0-9]", "", x, perl = TRUE)  748.432  756.3290  763.3345  779.4150 1127.759   100
                              gsub("[0-9]", "", x) 1452.630 1467.0205 1482.3825 1503.4140 1755.422   100
    

    【讨论】:

    • 只是好奇 - 这比 gsub 有什么优势?
    • @bartektartanus:很好奇,你能把它和gsub(..., perl=TRUE)比较一下吗?
    • 另外,\p{N}[0-9] 更广泛。 stri_replace_all_charclass也可以用[0-9]
    • 它更快,但仍然比stringi慢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 2020-09-27
    • 2021-01-04
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多