Как вычесть последовательные числа в списке - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть некоторый текст в кадре данных следующим образом

Ввод

rownumber  CStage
1           38-40cm
2           27-22
3           32cm and 40cm

Я хочу вычесть два числа в каждом CStage с выводом

Желаемый вывод

rownumber  CStage
1           2
2           5
3           8

Я использовал stringr::str_extract_all(df$CStage,"\\d{2}")

, который дает мне список с каждым элементом, содержащим два числа

[[1]]
[1] "38" "40"

[[2]]
[1] "27" "22"

[[3]]
[1] "32" "40"

Как я могу затем вычесть два числа (чтобы получить положительный результат)

Ответы [ 3 ]

0 голосов
/ 05 декабря 2018

Вы также можете sort и затем использовать diff.

sapply(regmatches(df1$CStage, gregexpr("\\d+", df1$CStage)), function(x)diff(sort(as.numeric(x))))
#[1] 2 5 8
0 голосов
/ 06 декабря 2018

1) strapply Это можно сделать компактно, используя strapply в gsubfn.Определите регулярное выражение таким образом, чтобы для каждого элемента CStage оно извлекало два числа в группах захвата, передавая их анонимной функции, определенной в нотации формулы, возвращающей абсолютное значение разности.

library(gsubfn)

transform(DF, CStage = strapply(CStage, 
                                "(\\d+)\\D+(\\d+)", 
                                ~ abs(as.numeric(x) - as.numeric(y)),
                                simplify = TRUE))

, давая:

  rownumber CStage
1         1      2
2         2      5
3         3      8

2) База R Решение базы R можно получить, заменив нецифры пробелами в CStage и прочитав их, используя read.table для созданияфрейм данных, имеющий столбцы V1 и V2.Вычтите эти столбцы и возьмите абсолютное значение.

transform(DF, CStage = with(read.table(text = gsub("\\D", " ", CStage)), abs(V1-V2)))

, давая:

  rownumber CStage
1         1      2
2         2      5
3         3      8

3) dplyr / tidyr Решение с использованием dplyr и tidyr с использованием аналогичного подходав (2):

library(dplyr)
library(tidyr)

DF %>%
  separate(CStage, into = c("V1", "V2"), sep = "\\D+", 
    extra = "drop", convert = TRUE) %>%
  mutate(CStage = abs(V1 - V2)) %>%
  select(rownumber, CStage)

, дающий:

  rownumber CStage
1         1      2
2         2      5
3         3      8

Примечание

Вводимый в воспроизводимом виде:

Lines <- "
rownumber,CStage
1,38-40cm
2,27-22
3,32cm and 40cm"

DF <- read.csv(text = Lines, as.is = TRUE)
0 голосов
/ 05 декабря 2018

Как упомянуто в комментариях @Cath, вы можете использовать sapply, преобразовать его в числовое и сделать между ними diff.

num_list <- stringr::str_extract_all(df$CStage,"\\d{2}")
abs(sapply(num_list, function(x) diff(as.numeric(x))))
#[1] 2 5 8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...