从字符串中提取数字,包括' |'

时间:2014-06-17 00:55:14

标签: regex string r split

我有数据,其中一些项目是以“|”分隔的数字,如:

head(mintimes)
[1] "3121|3151" "1171"      "1351|1381" "1050"      ""          "122" 
head(minvalues)
[1] 14    10    11    31 Inf    22

我想要做的是提取所有时间并将它们与最小值匹配。最终得到类似的东西:

times    values
3121     14
3151     14
1171     10
1351     11
1381     11
1050     31
122      22

我已尝试strsplit(mintimes, "|")而我已尝试过str_extract(mintimes, "[0-9]+"),但它们似乎无效。有什么想法吗?

8 个答案:

答案 0 :(得分:6)

|是正则表达式元字符。从字面上看,这些特殊字符需要使用[]\\进行转义(或者您可以在某些函数中使用fixed = TRUE)。因此,您对strsplit()的致电应该是

strsplit(mintimes, "[|]")

strsplit(mintimes, "\\|")

strsplit(mintimes, "|", fixed = TRUE)

关于使用stringr函数的其他尝试,str_extract_all()似乎可以解决问题。

library(stringr)
str_extract_all(mintimes, "[0-9]+")

要获得所需的结果

> mintimes <- c("3121|3151", "1171", "1351|1381", "1050", "", "122") 
> minvalues <- c(14, 10, 11, 31, Inf, 22)
> s <- strsplit(mintimes, "[|]")
> data.frame(times = as.numeric(unlist(s)), 
             values = rep(minvalues, sapply(s, length)))
#   times values
# 1  3121     14
# 2  3151     14
# 3  1171     10
# 4  1351     11
# 5  1381     11
# 6  1050     31
# 7   122     22

答案 1 :(得分:4)

默认情况下strsplit使用正则表达式和&#34; |&#34;进行拆分是正则表达式语法中的特殊字符。你可以逃避它

strsplit(mintimes,"\\|")

或者只是将fixed = T设置为不使用正则表达式

strsplit(mintimes,"|", fixed=T)

答案 2 :(得分:3)

我编写了一个名为cSplit的函数,它对这些类型的东西很有用。你可以从我的要点中得到它:https://gist.github.com/mrdwab/11380733

用法是:

cSplit(data.table(mintimes, minvalues), "mintimes", "|", "long")
#    mintimes minvalues
# 1:     3121        14
# 2:     3151        14
# 3:     1171        10
# 4:     1351        11
# 5:     1381        11
# 6:     1050        31
# 7:      122        22

它还有一个广泛的&#34;设置,以防对您有用:

cSplit(data.table(mintimes, minvalues), "mintimes", "|", "wide")
#    minvalues mintimes_1 mintimes_2
# 1:        14       3121       3151
# 2:        10       1171         NA
# 3:        11       1351       1381
# 4:        31       1050         NA
# 5:       Inf         NA         NA
# 6:        22        122         NA

注意:输出为data.table

答案 3 :(得分:2)

正如其他人所提到的,你需要转义|以将其字面包含在正则表达式中。与往常一样,我们可以通过多种方式为这只猫设置皮肤,这是使用stringr进行此操作的唯一方法:

x <- c("3121|3151", "1171", "1351|1381", "1050", "", "122")

library(stringr)
unlist(str_extract_all(x, "\\d+"))

# [1] "3121" "3151" "1171" "1351" "1381" "1050" "122"

如果您在数字字符串中有任何小数点,这将无法按预期工作,因此以下(除了|之外的任何内容)可能更安全:

unlist(str_extract_all(x, '[^|]+'))

# [1] "3121" "3151" "1171" "1351" "1381" "1050" "122" 

无论哪种方式,您可能希望将结果包装在as.numeric

答案 4 :(得分:2)

这是使用stri_split_fixed包中的stringi的另一种解决方案。作为附加价值,我们还会使用mapplydo.call

输入数据:

mintimes <- c("3121|3151", "1171", "1351|1381", "1050", "", "122") 
minvalues <- c(14, 10, 11, 31, Inf, 22)

拆分mintimes w.r.t. |并转换为数字:

library("stringi")    
mintimes <- lapply(stri_split_fixed(mintimes, "|"), as.numeric)
## [[1]]
## [1] 3121 3151
## 
## [[2]]
## [1] 1171
## 
## [[3]]
## [1] 1351 1381
## 
## [[4]]
## [1] 1050
## 
## [[5]]
## [1] NA
## 
## [[6]]
## [1] 122

将每个minvalues与相应的mintimes

进行列绑定
tmp <- mapply(cbind, mintimes, minvalues)
## [[1]]
##      [,1] [,2]
## [1,] 3121   14
## [2,] 3151   14
## 
## [[2]]
##      [,1] [,2]
## [1,] 1171   10
## 
## [[3]]
##      [,1] [,2]
## [1,] 1351   11
## [2,] 1381   11
## 
## [[4]]
##      [,1] [,2]
## [1,] 1050   31
## 
## [[5]]
##      [,1] [,2]
## [1,]   NA  Inf
## 
## [[6]]
##      [,1] [,2]
## [1,]  122   22

对所有6个矩阵进行行绑定&amp;删除NA - 行:

res <- do.call(rbind, tmp)
res[!is.na(res[,1]),]
##      [,1] [,2]
## [1,] 3121   14
## [2,] 3151   14
## [3,] 1171   10
## [4,] 1351   11
## [5,] 1381   11
## [6,] 1050   31
## [7,]  122   22

答案 5 :(得分:1)

要获得所需的输出,请尝试以下方法:

library(dplyr)

Split.Times <- function(x) {
  mintimes <- as.numeric(unlist(strsplit(as.character(x$mintimes), "\\|")))
  return(data.frame(mintimes = mintimes, minvalues = x$minvalues, stringsAsFactors=FALSE))
}

df <- data.frame(mintimes, minvalues, stringsAsFactors=FALSE)

df %>%
  filter(mintimes != "") %>%
  group_by(mintimes) %>%
  do(Split.Times(.))

这会产生:

  mintimes minvalues
1     1050        31
2     1171        10
3      122        22
4     1351        11
5     1381        11
6     3121        14
7     3151        14

(我从my answer here借来 - 这几乎是同一个问题/问题)

答案 6 :(得分:1)

这是一个qdap包方法:

mintimes <- c("3121|3151", "1171", "1351|1381", "1050", "", "122") 
minvalues <- c(14, 10, 11, 31, Inf, 22)

library(qdap)
list2df(setNames(strsplit(mintimes, "\\|"), minvalues), "times", "values")

##   times values
## 1  3121     14
## 2  3151     14
## 3  1171     10
## 4  1351     11
## 5  1381     11
## 6  1050     31
## 7   122     22

答案 7 :(得分:0)

您可以使用[:punct:]

strsplit(mintimes, "[[:punct:]]")