从字符串中提取模式,剥离文本,转换为数字并在 R data.table 中求和?

Extract pattern from string, strip text, convert to numeric and sum in R data.table?

我有一个(100k 行)data.table mydata,其中一列如下所示:

library(data.table)
library(stringr)

mdata <- data.table(A = c("17M1I26M570M20S1M", "17M1I260M570M20S1M"))

我如何有效地 - 最好是在 1 行代码中 - 提取 M 之前的所有数字(它们的长度可以是不同的数字),将它们转换为数字并求出它们的总和。

我已经设法通过 3 轮 sapply 函数做到了这一点,并创建了一些我不需要的附加列:

mdata$c <- sapply(mydata[, A], function(x) unlist(str_extract_all(x, "\d+M")))
mdata$c2 <-sapply(mydata[, c], function(x) unlist(as.numeric(gsub( "M", "",x))))
mdata$c3 <- sapply(mydata[,c2], function(x) sum(x))

是否有更简洁、计算效率更高的方法来做到这一点?

您可以创建一个函数来获取出现在字符串中所有字母 M 实例之前的数字的总和,然后在您的 data.table.

中创建一个列

示例代码如下:

# Load data.table and stringr packages
library(data.table)
library(stringr)

# Data provided in the question
mydata <- data.table(A = c("17M1I26M570M20S1M", "17M1I260M570M20S1M"))

# Function to grab the sum of numbers before the letter M in a string
sum_before_m <- function(x) {
  # Grab all numbers that appear before M
  matches <- str_match_all(x, "\d+(?=M)")
  # Grab the matches column in the list, transform to numeric, then sum
  sapply(matches, function(y) sum(as.numeric(y)))
}

# Run the function for the column A
mydata[, c := sum_before_m(A)]

mydata
#                     A   c
# 1:  17M1I26M570M20S1M 614
# 2: 17M1I260M570M20S1M 848

编辑: 使用@thelatemail 在评论中的建议更改了正则表达式以提高匹配效率。

这是一个简洁的方法。

library(dplyr)
library(tidyr)
library(stringi)
library(rex)

regex_1 = 
  rex(capture(digits),
      capture(letter) )

data = 
  data_frame(
    a = c("17M1I26M570M20S1M", 
          "17M1I260M570M20S1M") ) 

key = 
  data %>%
  select(a) %>%
  distinct %>%
  mutate(match_list = 
           a %>%
           stri_extract_all_regex(regex_1) ) %>%
  unnest(match_list) %>%
  extract(match_list,
          c("number", "letter"),
          regex_1) %>%
  group_by(a) %>%
  mutate(order = 1:n(),
         number = as.numeric(number))

key %>%
  group_by(a) %>%
  summarize(total = sum(number)) %>%
  right_join(data)