R:读取数据帧中的字符串并记录特定字母的位置

时间:2018-12-12 16:14:32

标签: r string parsing

我有一个数据框,其中的一列包含字符串及其分数。有没有一种方法来创建一个新的数据框,其中每个字符串中的特定字母的位置及其得分。这是一个示例数据框

df<- data.frame( string = do.call(paste0, replicate(10, sample(LETTERS, 5, TRUE), FALSE)),
             start = round(runif(5,100,500),0),
             score = round(runif(5,10,50),1)

head(df)

它看起来像这样:

String        start    score
TRIRXBGFPI    219      46.1
QBPWJOTFLQ    430      21.5
PWVEEHKTFW    399      37.2
AWGAFAHGQF    246      16.4
ZDLYRUTZBB    380      32.1

现在,我希望能够读取字符串的每个字母并记录每个“ B”的位置及其得分。所以预期的输出将是

string         position     start     score
TRIRXBGFPI     6            219       46.1
QBPWJOTFLQ     2            430       21.5
ZDLYRUTZBB     9            380       32.1
ZDLYRUTZBB     10           380       32.1

我的方法是在字符串列上使用grepl过滤掉不带B的字符串,然后运行两个for循环以读取每个字符串的每个字母并记录其位置。有人可以建议一种更好的方法吗?

谢谢

3 个答案:

答案 0 :(得分:2)

我们可以使用str_locate

library(tidyverse)
df %>% 
     mutate(position = str_locate_all(String, "B") %>%
                 map(~ .x[,1])) %>% 
     unnest
#      String start score position
#1 TRIRXBGFPI   219  46.1        6
#2 QBPWJOTFLQ   430  21.5        2
#3 ZDLYRUTZBB   380  32.1        9
#4 ZDLYRUTZBB   380  32.1       10

或使用gregexpr中的base R

lst <- lapply(gregexpr("B", df$String), function(x) as.numeric(x * NA^(x <  0)))
# or use strsplit to split the string and then get the index with which
#lst <- lapply(strsplit(df$String, ""), function(x) {
#       x1 <- which(x == "B")
#       if(length(x1) == 0) NA else x1})
out <- df[rep(seq_len(nrow(df)), lengths(lst)),]
out$position <- unlist(lst)
out1 <- out[!is.na(out$position),]
row.names(out1) <- NULL
out1
#      String start score position
#1 TRIRXBGFPI   219  46.1        6
#2 QBPWJOTFLQ   430  21.5        2
#3 ZDLYRUTZBB   380  32.1        9
#4 ZDLYRUTZBB   380  32.1       10

数据

df <- structure(list(String = c("TRIRXBGFPI", "QBPWJOTFLQ", "PWVEEHKTFW", 
"AWGAFAHGQF", "ZDLYRUTZBB"), start = c(219L, 430L, 399L, 246L, 
380L), score = c(46.1, 21.5, 37.2, 16.4, 32.1)), class = "data.frame", 
row.names = c(NA, -5L))

答案 1 :(得分:2)

另一个tidyverse选项,使用gregexpr ......

library(tidyverse)

df %>% 
  mutate(position = gregexpr("B", String)) %>% 
  unnest(position) %>% 
  filter(position>0)

      String start score position
1 TRIRXBGFPI   219  46.1        6
2 QBPWJOTFLQ   430  21.5        2
3 ZDLYRUTZBB   380  32.1        9
4 ZDLYRUTZBB   380  32.1       10

答案 2 :(得分:0)

R为基础:

df[["position"]] <- 
   sapply(gregexpr(pattern ='B', df[["String"]]), "[", 1)

subset(df, position > 0)
      String start score position
1 TRIRXBGFPI   219  46.1        6
2 QBPWJOTFLQ   430  21.5        2
5 ZDLYRUTZBB   380  32.1        9

数据:

df <- data.frame(
  String = c("TRIRXBGFPI", "QBPWJOTFLQ", "PWVEEHKTFW", "AWGAFAHGQF", "ZDLYRUTZBB"), 
  start = c(219L, 430L, 399L, 246L, 380L), 
  score = c(46.1, 21.5, 37.2, 16.4, 32.1)
)