Подсчитать каждый следующий вхождение строки в подстроку - PullRequest
0 голосов
/ 13 ноября 2018

сегодня я столкнулся с проблемой, которую не смог решить самостоятельно, несмотря на поиск решений - мне показалось, что либо мой подход неверен, либо никто не задал подобный вопрос.

Я играю с атрибуцией Маркова, поэтому у меня есть столбцы со строками, которые выглядят так:

A > B > B > C > B > A > C > B > A

и т.д.

... создается на основе функции postgresql 'string_agg'.

Я думаю, что для меня было бы важно назначить номер, за который каждая строка появляется во всей строке. Чтобы было ясно, в конце дня это будет выглядеть так:

A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3

Есть три основных проблемы:

  • есть около 100 различных типов элементов, которые могут быть подсчитаны, что может изменить его время, поэтому его трудно жестко кодировать,
  • набор данных составляет около 200 тыс. Строк,
  • строки могут быть длиной до нескольких сотен символов

Единственное, что мне пришло в голову, это написать какой-то цикл, но такое ощущение, что это займет много времени, пока не закончится.

Я также думал о том, чтобы решить эту проблему на уровне postgresql, но также не смог найти эффективное и простое решение.

Ответы [ 3 ]

0 голосов
/ 13 ноября 2018

Вот функция, которая использует только базу R.
Обратите внимание, что если вы используете другой набор метасимволов регулярных выражений, должно быть легко иметь аргумент функции metachar, по умолчанию равный тому, который указан в теле функции.

count_seq <- function(x, sep = ">"){
  metachar <- '. \ | ( ) [ { ^ $ * + ?'
  sep2 <- if(grepl(sep, metachar)) paste0("\\", sep) else sep
  y <- unlist(strsplit(x, sep2))
  y <- trimws(y)
  z <- ave(y, y, FUN = seq_along)
  paste(paste0(y, z), collapse = sep)
}

x <- "A > B > B > C > B > A > C > B > A"

count_seq(x)
#[1] "A1>B1>B2>C1>B3>A2>C2>B4>A3"
count_seq(x, sep = " > ")
#[1] "A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3"

y <- "A | B | B | C | B | A | C | B | A"
count_seq(y, sep = "|")
#[1] "A1|B1|B2|C1|B3|A2|C2|B4|A3"
0 голосов
/ 13 ноября 2018

Как это сделать, описано в gsubfn vignette .Используя этот код, мы сначала определяем объект прото pword с методами pre и fun.pre инициализирует список слов (в котором хранится текущий счетчик для каждого встреченного слова) и fun обновляет его каждый раз, когда встречается новое слово, а также суффикс слова с счетчиком, возвращающим слово с суффиксом.

Определив вышесказанное, запустите gsubfn, используя pword.Для каждого компонента ввода gsubfn сначала запустится pre, а затем для каждого совпадения регулярного выражения \\w+ gsubfn введет совпадение в fun, запустит fun и заменит совпадение выводом.из fun.

Мы предположили, что слова с суффиксом, равным количеству, совпадают с \w+, как в случае с примером в вопросе, но если ваши фактические данные отличаются, вам может потребоватьсяизменить шаблон.

library(gsubfn)
s <- rep("A > B > B > C > B > A > C > B > A", 3) # sample input

pwords <- proto(
  pre = function(this) { this$words <- list() },
  fun = function(this, x) {
    if (is.null(words[[x]])) this$words[[x]] <- 0
    this$words[[x]] <- this$words[[x]] + 1
    paste0(x, words[[x]])
  }
)

gsubfn("\\w+", pwords, s)

давая:

[1] "A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3"
[2] "A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3"
[3] "A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3"
0 голосов
/ 13 ноября 2018

Вот пример с использованием data.table:

library(data.table)

# Example data:
data <- data.table(
  s = c("A > B > B > C > B > A > C > B > A",
        "A > B > B > C > B > A > C > B > C > D")
)

# Processing steps (can probably be shortened)
n <- strsplit(data[["s"]], " > ")
datal <- melt(n)
setDT(datal)
datal[, original_order := 1:.N
      ][, temp := paste0(value, 1:.N), by = .(L1, value)
        ][order(original_order), paste(temp, collapse = " > "), by = L1]


# Output:
   L1                                              V1
1:  1      A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > A3
2:  2 A1 > B1 > B2 > C1 > B3 > A2 > C2 > B4 > C3 > D1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...