我需要从长度不规则的行中获取一些数字,如下所示:
AAAAAAAAA 250.00
BBB 240.00
CCCCCCC 13.00
我需要捕获250.00,240.00和13.00,但由于数字和字符串都是不规则的,我不能使用“substr”,我认为正则表达式可能是解决方案,但我不太关心它。 / p>
有人可以帮忙吗?谢谢!
编辑#1
感谢Joshua的快速回复,但我担心情况并非如此,因为空间和数字也可能出现在AAAAAAAA,BBB,CCCCC字符串中。
再次感谢。
编辑#2
约书亚我试过了,但仍然失败了,我会在这里展示一下这一行的样本:
01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 250.00
希望它有所帮助,再次感谢。
编辑#3
约书亚再次感谢。
现在我有一个更复杂的案例:
01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 250.00
“OCTOPUS CARDS LTD HONG KONG HK”和“834591283405347”是两个单独的栏目,我也想提取它们,我该怎么做?
答案 0 :(得分:2)
如果您的每一行数据中只有两列,则可以read.table()
使用textConnection()
:
x = "AAAAAAAAA 250.00
BBB 240.00
CCCCCCC 13.00"
data = read.table(textConnection(x))
data
V1 V2
1 AAAAAAAAA 250
2 BBB 240
3 CCCCCCC 13
和
data[2]
V2
1 250
2 240
3 13
答案 1 :(得分:2)
不幸的是尾巴相对较慢。实际上索引最终项目要快得多。
FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}
在我的机器上,这比tail命令快两倍。
y <- c("AAAAAAAAAAA 250.00",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 5.13",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 50.00")
#make y bigger so that there's something to test
y <- rep(y, 1e5)
#testing tail
FUN <- function(x) {tail(strsplit(x,' ')[[1]],1)}
system.time( lapply(y,FUN) )
user system elapsed
22.108 0.110 22.069
#testing indexing
FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}
system.time( lapply(y,FUN) )
user system elapsed
9.396 0.037 9.372
但是通过将功能分离并利用组件已经被矢量化的事实来实现更高的速度。 (应用族命令的重点不是取代循环,而是允许简单的语法并尽可能使用矢量化命令。最简单的函数应该用于lapply等。)
#first let strsplit do it's own vectory magic
s <- strsplit(y, ' ')
#then define a simpler function
FUN <- function(x) x[length(x)]
lapply(s, FUN)
要对此进行时间测试,有必要将strsplit保持在计时例程中以使其公平
system.time( {s <- strsplit(y, ' ');lapply(s, FUN)} )
user system elapsed
5.281 0.048 5.305
(我很确定我在索引列表上遗漏了一些东西,我的功能应该更简单。)
还有一件事......这会让事情一路加快,但我会在这里添加它。 strsplit()有一个固定的选项。如果在不使用正则表达式时将其设置为true,则工作速度会快得多。
system.time( {s <- strsplit(y, ' ', fixed = TRUE); lapply(s, FUN)} )
user system elapsed
1.256 0.007 1.253
如果您在大型数据集上执行此操作,或者您必须经常在中等大小的数据集上执行此操作,那么您应该使用最后一种方法。它快了近20倍。
这是可以复制完成整个任务的最终解决方案,假设Y是在Edit#3中按预期格式化的字符串向量。预期的是,最后一项是要保存的货币值,第二项是某种ID值。
s <- strsplit(y, ' ', fixed = TRUE)
moneyVal <- lapply(s, function(x) x[length(x)])
idVal <- lapply(s, function(x) x[length(x)-1])
restOfY <- lapply(s, function(x) paste(x[1:(length(x)-2)], collapse = ' '))
#These three values can be combined into a data frame
df <- data.frame(restOfY, idVal, moneyVal)
答案 2 :(得分:1)
如果您的实际问题与您的示例相同:
> lapply(c("AAAAAAA 250.00","BBB 240.00"), function(x) strsplit(x, " ")[[1]][2])
[[1]]
[1] "250.00"
[[2]]
[1] "240.00"
编辑1:由于您的实际问题不像您的例子完全:; - )
> y <- c("AAAAAAAAAAA 250.00","BBBBB 240.00","CC CC 120.00")
> FUN <- function(x) substr(x,regexpr("[0-9]",x),nchar(x))
> lapply(y,FUN)
[[1]]
[1] "250.00"
[[2]]
[1] "240.00"
[[3]]
[1] "120.00"
编辑2:
将FUN
更改为:
> FUN <- function(x) tail(strsplit(x," ")[[1]],1)
答案 3 :(得分:0)
我想要更多信息确定。但它总是“任意文本[空格]数字”吗?
如果是这样,你可以做类似
的事情> read.csv("~/Desktop/test.txt", sep=" ", header=FALSE)
V1 V2
1 AAAAAAAAA 250
2 BBB 240
3 CCCCCCC 13
假设您已将文本保存到文件(〜/ Desktop / test.txt)。数字字符串会自动强制转换为数字。
> sum(a$V2)
[1] 503
答案 4 :(得分:0)
使用gsub
:
y <- c(
"AAAAAAAAAAA 250.00",
"BBBBB 240.00",
"CC CC 120.00",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 250.00",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 250.00"
)
gsub("(^.* )([0-9\\.]*$)", "\\2", y)
# [1] "250.00" "240.00" "120.00" "250.00" "250.00"
或
gsub("^.* ", "", y)
# [1] "250.00" "240.00" "120.00" "250.00" "250.00"
答案 5 :(得分:0)
你应该看一下gsubfn包,特别是strapply函数。
strapply功能专注于您想要找到的内容(不是您想要分割的内容,或者您要删除的内容)。
一个简单的例子就是给它一个匹配数字的模式,它会给你字符串中的所有数字,或者你可以包含'$'来只获取字符串末尾的数字,或修改模式与你想要的完全匹配。