如何从R中的字符串中提取数字?

时间:2019-01-08 20:53:46

标签: r regex

我有一个这样的数据框:

    > dns1
               variant_id         gene_id pval_nominal
21821  chr1_165656237_T_C_b38 ENSG00000143149  1.24119e-05
21822 chr1_165659346_C_CA_b38 ENSG00000143149  1.24119e-05
21823  chr1_165659350_A_G_b38 ENSG00000143149  1.24119e-05
21824  chr1_165659415_A_G_b38 ENSG00000143149  1.24119e-05
21825  chr1_165660430_T_C_b38 ENSG00000143149  1.24119e-05
21826  chr1_165661135_T_G_b38 ENSG00000143149  1.24119e-05
21827  chr1_165661238_C_T_b38 ENSG00000143149  1.24119e-05
...

我想从第二列(variant_id)中删除所有字符,只提取第二个数字,看起来像这样:

165656237
165659346
165659350
165659415
165660430
165661135
165661238
...

我尝试过:

dns1$variant_id <- gsub('[^0-9.]','',dns1$variant_id)

但是使用上面的命令,我得到了:

> dns1
      variant_id         gene_id pval_nominal
21821    116565623738 ENSG00000143149  1.24119e-05
21822    116565934638 ENSG00000143149  1.24119e-05
21823    116565935038 ENSG00000143149  1.24119e-05
21824    116565941538 ENSG00000143149  1.24119e-05
...

所以这将匹配variant_id列中的所有数字,而我需要获取16565623738而不是116565623738。所以问题是如何在第二列中仅匹配第二个数字?

5 个答案:

答案 0 :(得分:4)

您可以使用

dns1$variant_id <- sub('^[^_]*_(\\d+).*', '\\1', dns1$variant_id)

请参见regex demo

详细信息

  • ^-字符串的开头
  • [^_]*-除_以外的0多个字符
  • _-下划线
  • (\\d+)-第1组:一个或多个数字
  • .*-字符串的其余部分。

sub函数将仅对每个字符串执行一次搜索和替换操作,而替换中的\1后向引用将把组1中的内容放回去。

Online R demo

variant_id <- c("chr1_165656237_T_C_b38", "chr1_165659346_C_CA_b38")
dns1 <- data.frame(variant_id)
dns1$variant_id <- sub('^[^_]*_(\\d+).*', '\\1', dns1$variant_id)
dns1
##=> variant_id
## 1  165656237
## 2  165659346

答案 1 :(得分:4)

我相信您可以按以下方式捕获数字:

gsub(".*?_([[:digit:]]+)_.*", "\\1", dns1$variant_id)

答案 2 :(得分:1)

这是一个超级hacky解决方案,它同时使用gsub和str_replace(来自stringr)。我确定有更好的解决方案,并且这要求variant_id始终以chr1_开头,这可能不公平。

dns1$variant_id <- gsub('_(.*)','', str_replace(dns1$variant_id, 'chr1_',''))

答案 3 :(得分:1)

以下是使用stringr的选项:

library(stringr)

df <-
  data.frame(variant_id = c("chr1_165656237_T_C_b38",
                            "chr1_165659346_C_CA_b38",
                            "chr1_165659350_A_G_b38",
                            "chr1_165659415_A_G_b38",
                            "chr1_165660430_T_C_b38",
                            "chr1_165661135_T_G_b38",
                            "chr1_165661238_C_T_b38"))

df$variant_id_extract <-
  str_replace(df$variant_id, "^.+_(\\d+)_.+$", "\\1")

df
#>                variant_id variant_id_extract
#> 1  chr1_165656237_T_C_b38          165656237
#> 2 chr1_165659346_C_CA_b38          165659346
#> 3  chr1_165659350_A_G_b38          165659350
#> 4  chr1_165659415_A_G_b38          165659415
#> 5  chr1_165660430_T_C_b38          165660430
#> 6  chr1_165661135_T_G_b38          165661135
#> 7  chr1_165661238_C_T_b38          165661238

答案 4 :(得分:1)

您可以使用

dns$variant_id_new <- sapply(strsplit(as.character(dns$variant_id), "_"), unlist)[2,]

从逻辑上讲,这首先将variant_id中的所有字符串除以_sapply(,unlist)将其转换为矩阵,在此我们取第二行(用于第二个变量)。