我有一个看起来像这样的字符串:
x <- "\r\n Ticker Symbol: RBO\r\n \t Exchange: TSX \r\n\t Assets ($mm) 36.26 \r\n\t Units Outstanding: 1,800,000 \r\n\t Mgmt. Fee** 0.25 \r\n 2013 MER* n/a \r\n\t CUSIP: 74932K103"
我需要的是:
list(Ticker = "RBO", Assets = 36.26, Shares = 1,800,000)
我尝试过分裂,正则表达式等等。但我觉得我的字符串操作技能不符合要求。
到目前为止,这是我的“最佳”尝试。
x <- unlist(strsplit(unlist(strsplit(x, "\r\n\t") ),"\r\n"))
trim <- function (x) gsub("^\\s+|\\s+$", "", x)
x <- trim(x)
gsub("[A-Z]+$","\\2",x[2]) # bad attempt to get RBO
答案 0 :(得分:1)
也许:
sub( "\\\r\\\n.+$", "", sub( "^.+Ticker Symbol: ", "", x) )
[1] "RBO"
我想你可以用括号在一个模式中完成所有操作。和反向引用。
> sub( "^.+Ticker Symbol: ([[:alpha:]]{1,})\\\r\\\n.+$", "\\1", x)
[1] "RBO"
答案 1 :(得分:1)
更新/更好的回答:
看看cat(x)
和readLines(x)
在这里有很多帮助
> cat(x)
#
# Ticker Symbol: RBO
# Exchange: TSX
# Assets ($mm) 36.26 #
# Units Outstanding: 1,800,000
# Mgmt. Fee** 0.25
# 2013 MER* n/a
# CUSIP: 74932K103
> readLines(textConnection(x))
# [1] "" " Ticker Symbol: RBO"
# [3] " \t Exchange: TSX " "\t Assets ($mm) 36.26 "
# [5] "\t Units Outstanding: 1,800,000 " "\t Mgmt. Fee** 0.25 "
# [7] " 2013 MER* n/a " "\t CUSIP: 74932K103"
现在我们知道一些事情。一,我们不需要第一行,我们做想要第二行。这使事情变得更容易,因为现在第一行匹配我们想要的第一行。接下来,列表名称与字符串中的名称匹配会更容易。我选择了这些。
> nm <- c("Symbol", "Assets", "Units")
现在我们必须使用grep
与sapply
一起使用,我们将返回一个命名的匹配向量。在value = TRUE
中设置grep
会将字符串返回给我们。
> (y <- sapply(nm, grep, x = readLines(textConnection(x))[-1], value = TRUE))
# b Symbol Assets
# " Ticker Symbol: RBO" "\t Assets ($mm) 36.26 "
# Units
# "\t Units Outstanding: 1,800,000 "
然后我们strsplit
在"[: ]"
上,取每个分组中的最后一个元素,然后我们就完成了。
> lapply(strsplit(y, "[: ]"), tail, 1)
$Symbol
[1] "RBO"
$Assets
[1] "36.26"
$Units
[1] "1,800,000
您可以使用
获得相同的结果> g <- gsub("[[:cntrl:]]", "", capture.output(cat(x))[-1])
> m <- mapply(grep, nm, MoreArgs = list(x = g, value = TRUE))
> lapply(strsplit(m, "[: ]"), tail, 1)
希望有所帮助。
原始答案:
看起来如果你从大桌子中拉出这些,他们都会在同一个元素中插入#34; slot&#34;每一次,也许这可能会更容易一些。
> s <- strsplit(x, "[: ]|[[:cntrl:]]")[[1]]
说明:
- [: ]
匹配":"
字符,后跟空格字符
- |
或
- [[:cntrl:]]
任何控制字符,在本例中为\r
,\t
和\n
中的任何一个。这可能更好地解释了here
然后,nzchar
在上面的结果中查找非零长度字符串,如果匹配则返回TRUE,否则返回FALSE。因此,我们可以查看第一行的结果,确定匹配的位置,以及基于此的子集。
> as.list(s[nzchar(s)][c(3, 8, 11)])
[[1]]
[1] "RBO"
[[2]]
[1] "36.26"
[[3]]
[1] "1,800,000"
您可以通过将s
指定为内部调用来将is放入一行。由于函数和调用是由内到外计算的,因此在R到达外部s
子集之前会分配s
。但这可读性稍差。
s[nzchar(s <- strsplit(x, "[: ]|[[:cntrl:]]")[[1]])][c(3,8,11)]
所以这将是s <- strsplit(...)
- &gt; [[
- &gt; nzchar
- &gt; s[..
&gt; - [c(3,8,11)]
答案 2 :(得分:1)
如果您只想提取字符串的不同部分,可以使用regexpr
查找短语并在短语后提取内容。例如
extr<-list(
"Ticker" = "Ticker Symbol: ",
"Assets" = "Assets ($mm) ",
"Shares" = "Units Outstanding: "
)
lines<-strsplit(x,"\r\n")[[1]]
Map(function(p) {
m <- regexpr(p, lines, fixed=TRUE)
if(length( w<- which(m!=-1))==1) {
gsub("^\\sw+|\\s$", "",
substr(lines[w], m[w] + attr(m,"match.length")[w], nchar(lines[w])))
} else {
NA
}
}, extr)
根据需要返回命名列表
$Ticker
[1] "RBO"
$Assets
[1] "36.26"
$Shares
[1] "1,800,000"
此处extr
是一个列表,其中元素的名称是将在最终列表中使用的名称,元素值是将在文本中匹配的确切字符串。我还在gsub
添加了任何空格。
答案 3 :(得分:1)
stringr
包适用于从字符串中抓取数据。以下是我每次使用的步骤。您可以随时根据需要制定具体或强大的规则。
require(stringr)
## take out annoying characters
x <- gsub("\r\n", "", x)
x <- gsub("\t", "", x)
x <- gsub("\\(\\$mm\\) ", "", x)
## define character index positions of interest
tickerEnd <- str_locate(x, "Ticker Symbol: ")[[1, "end"]]
assetsEnd <- str_locate(x, "Assets ")[[1, "end"]]
unitsStart <- str_locate(x, "Units Outstanding: ")[[1, "start"]]
unitsEnd <- str_locate(x, "Units Outstanding: ")[[1, "end"]]
mgmtStart <- str_locate(x, "Mgmt")[[1, "start"]]
## get substrings based on indices
tickerTxt <- substr(x, tickerEnd + 1, tickerEnd + 4) # allows 4-character symbols
assetsTxt <- substr(x, assetsEnd + 1, unitsStart - 1)
sharesTxt <- substr(x, unitsEnd + 1, mgmtStart - 1)
## cut out extraneous characters
ticker <- gsub(" ", "", tickerTxt)
assets <- gsub(" ", "", assetsTxt)
shares <- gsub(" |,", "", sharesTxt)
## add data to data frame
df <- data.frame(ticker, as.numeric(assets), as.numeric(shares), stringsAsFactors = FALSE)