我有如下数据。我希望从名为my.string
的每个字符串中提取第一年和最后一年。有些字符串只包含一年,有些字符串不包含年份。没有字符串包含超过两年。我在示例数据集下面的名为desired.result
的对象中提供了所需的结果。我正在使用R
。
当字符串包含两年时,这些年份包含在字符串的一部分中,该字符串看起来像ga49.51
或ea22.24
当一个字符串只包含一年时,该字符串的一部分包含在该字符串的一部分中:time11
我对regex
了解一点,但这个问题看起来太不规则和复杂了。我甚至不知道从哪里开始。谢谢你的任何建议。
修改
也许删除第一个冒号(:)之前的数字,剩下的数字就是我想要的。
my.data <- read.table(text = '
my.string cov1 cov2
42:Alpha:ga6.8 -0.1 2.2
43:Alpha:ga9.11 -2.5 0.6
44:Alpha:ga30.32 -1.3 0.5
45:Alpha:ga49.51 -2.5 0.6
50:Alpha:time1:ga.time -1.7 0.9
51:Alpha:time2:ga.time -1.5 0.8
52:Alpha:time3:ga.time -1.0 1.0
2:Beta:ea2.9 -1.7 0.6
3:Beta:ea17.19 -5.0 0.8
4:Beta:ea22.24 -6.4 1.0
8:Beta:as 0.2 0.6
9:Beta:sd 1.7 0.4
12:Beta:time1:ea.tim -2.6 1.8
13:Beta:time10:ea.ti -3.6 1.1
14:Beta:time11:ea.ti -3.1 0.7
', header = TRUE, stringsAsFactors = FALSE, na.strings = "NA")
desired.result <- read.table(text = '
my.string cov1 cov2 time1 time2
42:Alpha:ga6.8 -0.1 2.2 6 8
43:Alpha:ga9.11 -2.5 0.6 9 11
44:Alpha:ga30.32 -1.3 0.5 30 32
45:Alpha:ga49.51 -2.5 0.6 49 51
50:Alpha:time1:ga.time -1.7 0.9 1 NA
51:Alpha:time2:ga.time -1.5 0.8 2 NA
52:Alpha:time3:ga.time -1.0 1.0 3 NA
2:Beta:ea2.9 -1.7 0.6 2 9
3:Beta:ea17.19 -5.0 0.8 17 19
4:Beta:ea22.24 -6.4 1.0 22 24
8:Beta:as 0.2 0.6 NA NA
9:Beta:sd 1.7 0.4 NA NA
12:Beta:time1:ea.tim -2.6 1.8 1 NA
13:Beta:time10:ea.ti -3.6 1.1 10 NA
14:Beta:time11:ea.ti -3.1 0.7 11 NA
', header = TRUE, stringsAsFactors = FALSE, na.strings = "NA")
答案 0 :(得分:2)
我建议使用 stringr 库来提取您需要的数据,因为它可以更好地处理NA值,并且还允许使用约束宽度 lookbehind:
> library(stringr)
> my.data$time1 <- str_extract(my.data$my.string, "(?<=time)\\d+|(?<=\\b[ge]a)\\d+")
> my.data$time2 <- str_extract(my.data$my.string, "(?<=\\b[ge]a\\d{1,100}\\.)\\d+")
> my.data
my.string cov1 cov2 time1 time2
1 42:Alpha:ga6.8 -0.1 2.2 6 8
2 43:Alpha:ga9.11 -2.5 0.6 9 11
3 44:Alpha:ga30.32 -1.3 0.5 30 32
4 45:Alpha:ga49.51 -2.5 0.6 49 51
5 50:Alpha:time1:ga.time -1.7 0.9 1 <NA>
6 51:Alpha:time2:ga.time -1.5 0.8 2 <NA>
7 52:Alpha:time3:ga.time -1.0 1.0 3 <NA>
8 2:Beta:ea2.9 -1.7 0.6 2 9
9 3:Beta:ea17.19 -5.0 0.8 17 19
10 4:Beta:ea22.24 -6.4 1.0 22 24
11 8:Beta:as 0.2 0.6 <NA> <NA>
12 9:Beta:sd 1.7 0.4 <NA> <NA>
13 12:Beta:time1:ea.tim -2.6 1.8 1 <NA>
14 13:Beta:time10:ea.ti -3.6 1.1 10 <NA>
15 14:Beta:time11:ea.ti -3.1 0.7 11 <NA>
第一个正则表达式匹配:
(?<=time)\\d+
- 在他们之前有time
的1位数字|
- 或(?<=\\b[ge]a)\\d+
- 前面有ge
或ea`作为整个单词的1位数字第二个正则表达式匹配:
(?<=\\b[ge]a\\d{1,100}\\.)
- 检查当前位置是否以ge
或ea
作为整个单词后跟1到100位数(我相信这对于您的方案应该足够了,100 - 这里几乎没有预期的数据块,你甚至可以减少这个数值),然后是.
\\d+
- 1+位数答案 1 :(得分:1)
这是一个正则表达式,它将提取两种类型中的任何一种,并将它们输出到行尾的不同列:
搜索:.*(?:time(\d+)|(?:[ge]a)(\d+)\.(\d+)).*
替换:$0\t$1\t$2\t$3
<强>故障:强>
.*(?:
... ).*
确保整条线匹配,并使用非捕获组进行主要更改time(\d+)
:这是交替的前半部分,在“时间”之后捕获任何数字(?:[ge]a)(\d+)\.(\d+)
:交替的后半部分匹配“ga”或“ea”,后跟两组数字,每组都在自己的捕获组中$0
将整条线放回去。将添加其他每个捕获组,并在其间添加选项卡。