【问题标题】:Create new column based on last 2 digits of values in another column根据另一列中值的最后 2 位创建新列
【发布时间】:2020-02-12 19:20:47
【问题描述】:

应该足够简单,但它已成为一个难以解决的问题。我有按尾随小数分组的数据(上游数据源的产物)。例如,可以将组“3”的数据分组为 0.00003,而组“10”的数据为 24.00010。但是,当我同时运行 regexpr 代码和 str_sub 代码时,就好像 R 不认为最后一个 0 很重要。


示例数据

df <- data.frame(a = c(0.00003, 0.00010, 24.00003, 24.00010))

print(df)
         a
1  0.00003
2  0.00010
3 24.00003
4 24.00010

期望的输出

         a   group
1  0.00003 group03
2  0.00010 group10
3 24.00003 group03
4 24.00010 group10

尝试 1 失败

df %>% mutate(group = paste0("group", regmatches(a, regexpr("(\\d{2}$)", a))))         
         a   group
1  0.00003 group03
2  0.00010 group01
3 24.00003 group03
4 24.00010 group01

这个失败很奇怪,因为当我检查它时它有效:https://regexr.com/,使用(\d{2}$)


尝试 2 失败

df %>% mutate(group = paste0("group", str_sub(a, start = -2)))
         a   group
1  0.00003 group03
2  0.00010 group01
3 24.00003 group03
4 24.00010 group01

【问题讨论】:

    标签: r regex string


    【解决方案1】:

    这里的关键是,当您使用正则表达式进行子串或提取时,您正在将数字转换为字符串。但是,该字符串不会保持您期望的格式。

    library(tidyverse)
    
    tibble(a = c(0.00003, 0.00010, 24.00003, 24.00010)) %>%
      mutate(group1 = paste0("group", str_extract(sprintf("%.5f", a), "\\d{2}$")),
             group2 = paste0("group", str_extract(a, "\\d{2}$")),
             sprint_char = sprintf("%.5f", a),
             char = as.character(a))
    #> # A tibble: 4 x 5
    #>          a group1  group2  sprint_char char    
    #>      <dbl> <chr>   <chr>   <chr>       <chr>   
    #> 1  0.00003 group03 group05 0.00003     3e-05   
    #> 2  0.0001  group10 group04 0.00010     1e-04   
    #> 3 24.0     group03 group03 24.00003    24.00003
    #> 4 24.0     group10 group01 24.00010    24.0001
    

    请参见此处as.character(a)a 的结构不同。您可以改为使用sprintf 设置格式,然后提取所需的文本。

    【讨论】:

    • 谢谢!你的解释太棒了,很容易理解!工作得很好!我选择了您的答案,因为它不仅有效,而且最具描述性。
    【解决方案2】:

    我们可以转换为character 并使用str_sub。另外,请确保设置了options

    options(scipen = 999)
    library(stringr)
    library(dplyr)
    df %>% 
       mutate(group = paste0("group", str_sub(sprintf("%2.5f", a), start = -2)))
    #        a   group
    #1  0.00003 group03
    #2  0.00010 group10
    #3 24.00003 group03
    #4 24.00010 group10
    

    【讨论】:

    • 效果很好!很简单!
    【解决方案3】:
    df$group <- sprintf('%s%02.0f', 'group', 1e5*(df$a %% .001))
    
    df
    #          a   group
    # 1  0.01003 group03
    # 2  0.03010 group10
    # 3 24.03003 group03
    # 4 24.00010 group10
    

    【讨论】:

      猜你喜欢
      • 2021-12-02
      • 2020-04-16
      • 2022-08-12
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多