• найти строку по ключевым словам и проверить, находится ли дата между начальной и конечной датой - PullRequest
0 голосов
/ 10 мая 2018

У меня есть набор предложений,

{ cat ate rat, rat was killed, cat killed the rat, rat killed by rat}.

Первый) Я хочу найти, содержит ли значение в столбце col2 какое-либо из этих предложений

Секунда) Если есть совпадение, то я хочу проверить, находится ли дата в Col3 между датами начала и окончания в col4 и col5.

Вот тестовый набор данных

Id      Col2                Col3        Col4        Col5
1       This cat            05-09-2001  04-10-2000  09-14-2001
2       This cat ate a rat  05-04-2011  05-01-2011  05-14-2011
3       Cat was killed      02-04-2015  02-01-2015  03-12-2015
4       Cat killed the rat  10-06-2014  09-20-2014  10-11-2014
5       Rat ran away        03-12-2008  04-12-2015  04-20-2015

Это ожидаемый результат

Id      Col2                Col3        Col4        Col5         Event
1       This cat            05-09-2001  04-10-2000  09-14-2001   No
2       Cat ate rat         05-04-2011  05-01-2011  05-14-2011   Yes
3       Cat died            02-04-2015  02-01-2015  03-12-2015   No
4       Cat killed the rat  10-06-2014  09-20-2014  10-11-2014   Yes
5       Rat ran away        03-12-2008  04-12-2015  04-20-2015   No

Это то, что id делал до сих пор. Код ниже работает. Я получаю результаты, которые хочу, но это очень неэффективно. Это очень медленно и занимает много времени. Особенно, если мой df содержит 3 миллиона строк, мне понадобится 10 дней, чтобы закончить выполнение этого кода. Любые советы по эффективному способу решения этой проблемы очень ценятся.

ключевые слова <- c ("кошка съела крысу", "крыса была убита", "кошка убила крысу", "крыса убита крысой") </p>

for (i in 1:NROW(Df)) {

         if( NROW(Df[grep(paste0(keywords, collapse = "|"), Df$Col2[i]),]) > 0) {

             if ( (Df$Col3[i] > Df$Col4[i]) & (Df$Col3[i] < Df$Col5[i]) ){
               Df$Event <- "Yes"
             } else {
               Df$Event <- "No"
             }


         }
        print(i)
      }

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Краткий ответ:

df$Event <- sapply(tolower(df$Col2), function(el) el %in% sentences)

делает то, что вы хотите в цикле for.

В R вы должны избегать циклов for и пытаться использовать функции apply -семейства . tolower делает содержимое df $ Col2 строчными. Для каждого элемента этого вектора столбца определенная функция function(el) el %in% sentences имеет значение apply (она спрашивает, является ли каждый элемент частью символьного вектора sentences, и дает ли логический результат сначала собирается в список, но затем пытается s включить собранные результаты далее в вектор (sapply).

Полная рабочая версия кода:

Считывание и подготовка данных

sentences <- unlist(strsplit("cat ate rat, rat was killed, cat killed the rat, rat killed by rat",", "))

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

txt2df <- function(dfstr) {
  lines <- unlist(strsplit(txt, "\n"))
  l <- unlist(lapply(lines,strsplit, "\ {2, }"), recursive = FALSE)
  df <- as.data.frame(Reduce(rbind, l[2:length(l)]), row.names = FALSE)
  colnames(df) <- l[[1]]
  df
}

применить функцию к многострочной строке для получения data.frame:

df <- txt2df("Id      Col2                Col3        Col4        Col5
1       This cat            05-09-2001  04-10-2000  09-14-2001
2       This cat ate a rat  05-04-2011  05-01-2011  05-14-2011
3       Cat was killed      02-04-2015  02-01-2015  03-12-2015
4       Cat killed the rat  10-06-2014  09-20-2014  10-11-2014
5       Rat ran away        03-12-2008  04-12-2015  04-20-2015")


df

  Id               Col2       Col3       Col4       Col5
1  1           This cat 05-09-2001 04-10-2000 09-14-2001
2  2 This cat ate a rat 05-04-2011 05-01-2011 05-14-2011
3  3     Cat was killed 02-04-2015 02-01-2015 03-12-2015
4  4 Cat killed the rat 10-06-2014 09-20-2014 10-11-2014
5  5       Rat ran away 03-12-2008 04-12-2015 04-20-2015

Функция поиска

поиск, если любое из предложений в нижнем регистре значений df $ Col2:

df$Event <- sapply(tolower(df$Col2), function(el) el %in% sentences)

Результат

df

  Id               Col2       Col3       Col4       Col5 Event
1  1           This cat 05-09-2001 04-10-2000 09-14-2001 FALSE
2  2 This cat ate a rat 05-04-2011 05-01-2011 05-14-2011 FALSE
3  3     Cat was killed 02-04-2015 02-01-2015 03-12-2015 FALSE
4  4 Cat killed the rat 10-06-2014 09-20-2014 10-11-2014  TRUE
5  5       Rat ran away 03-12-2008 04-12-2015 04-20-2015 FALSE
0 голосов
/ 10 мая 2018

В основном вам нужно протестировать три условия.

  • Col3> = Col4
  • Col3 <= <code>Col5
  • Col2 присутствует в ключевых словах

Используйте векторизованные функции, такие как ifelse или %in%, чтобы ускорить ваш код.

mydf <- structure(list(Id = 1:5, Col2 = c("This cat", "This cat ate a rat", 
"Cat was killed", "Cat killed the rat", "Rat ran away"), Col3 = structure(c(11451, 
15098, 16470, 16349, 13950), class = "Date"), Col4 = structure(c(11057, 
15095, 16467, 16333, 16537), class = "Date"), Col5 = structure(c(11579, 
15108, 16506, 16354, 16545), class = "Date")), .Names = c("Id", 
"Col2", "Col3", "Col4", "Col5"), row.names = c(NA, -5L), class = "data.frame")

keywords <- c("cat ate rat", "rat was killed", "cat killed the rat", "rat killed by rat")

mydf$event <- ifelse((mydf$Col3 >= mydf$Col4) & (mydf$Col3 <= mydf$Col5) 
                      & mydf$Col2 %in% keywords, "Yes", "No")

Обратите внимание, что эта версия чувствительна к регистру. Вас могут заинтересовать такие функции, как tolower.

mydf$event <- ifelse((mydf$Col3 >= mydf$Col4) & (mydf$Col3 <= mydf$Col5) 
                     & tolower(mydf$Col2) %in% keywords, "Yes", "No")
...