1

我有一个看起来像这样的字符串:

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
4

4 回答 4

1

也许:

 sub( "\\\r\\\n.+$", "", sub( "^.+Ticker Symbol: ", "", x) )
[1] "RBO"

我想你可以用括号以一种模式完成所有操作。和反向引用。

> sub( "^.+Ticker Symbol: ([[:alpha:]]{1,})\\\r\\\n.+$", "\\1", x)
[1] "RBO"
于 2014-08-06T17:53:31.410 回答
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")

现在我们要做的就是使用grepwith sapply,我们将得到一个命名的匹配向量。设置将返回我们value = TRUEgrep字符串。

> (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 " 

然后我们strspliton "[: ]",取每个拆分中的最后一个元素,我们就完成了。

> 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)

希望有帮助。


原答案:

看起来如果你从一张大桌子上拉出这些,它们每次都会在同一个元素“槽”中,所以这可能会更容易一些。

> s <- strsplit(x, "[: ]|[[:cntrl:]]")[[1]]

解释:
-[: ]匹配一个":"字符后跟一个空格字符
-|
-[[:cntrl:]]任何控制字符,在这种情况下是\r,\t和中的任何一个\n。这可能在这里得到更好的解释

然后,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 放入一行。由于函数和调用是从内向外评估的,s因此在 R 到达外部s子集之前分配。不过,这有点可读性差。

s[nzchar(s <- strsplit(x, "[: ]|[[:cntrl:]]")[[1]])][c(3,8,11)]

所以这会s <- strsplit(...)-> [[-> nzchar-> s[..>-[c(3,8,11)]

于 2014-08-06T17:55:24.703 回答
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是一个列表,其中元素的名称是将在最终列表中使用的名称,元素值是将在文本中匹配的确切字符串。我还添加了 agsub以修剪任何空白。

于 2014-08-06T18:12:09.400 回答
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)
于 2014-08-06T18:44:44.817 回答