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

时间:2015-11-27 00:39:04

标签: regex r data.table sapply

我有一个(100k行)data.table mydata,其中一列看起来像这样:

library(data.table)
library(stringr)

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

我如何有效 - 最好是在一行代码中 - 拉出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))

是否有更清洁,计算更有效的方法来做到这一点?

2 个答案:

答案 0 :(得分:3)

您可以创建一个函数来获取字符串中字母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的建议更改了正则表达式,以便更有效地进行匹配。

答案 1 :(得分:0)

这是一种整洁的方式。

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)