R: grep непреднамеренно выводит более одного совпадения строки - PullRequest
0 голосов
/ 15 мая 2019

У меня есть фрейм данных с 1 переменной и 5000 строк, где каждый элемент является строкой.

1. "Am open about my feelings."                   
2. "Work hard"                                 
3. "Work harder than others."
   .....
5000. "Speak softly."           

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

z <- lapply(df, function(p) {
     grep(pattern = p, test[ , 1])})

Работает хорошо и выводит индексы строк для каждого элемента, который я ищу. Но я заметил, что он становится жадным, так что код не только находит точные строки, но и строки большего размера, которые содержат исходную строку. Например, если в коде выполняется поиск индекса строки элемента «Работать усердно», он выведет 2 индекса строки. Один - для точного соответствия, а другой - для более крупной строки, содержащей исходную строку: «Работай усерднее, чем другие».

[1] 2 3

Пока я только частично решил проблему:

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

grep("\\bWork hard*\\b", df$value)

Поскольку это неэффективное решение, я хотел бы попросить помощи в настройке кода lapply, чтобы он мог найти только точную строчку. Я также попытался добавить "\\ b" и "* \\ b" в различные части кода, но безуспешно.

EDIT. Добавлен воспроизводимый пример

test_1 - это фрейм данных, содержащий почти 5000 строковых элементов, но для
Небольшой воспроизводимый пример, я приведу только 5 строковых элементов

test_1 <- c( 
         "Like to watch children open presents.",         
          "Work hard.",                              
          "Work harder after a failure.",                   
          "Am open about my feelings.",                
          "Show my sadness.")

library(dplyr)

test_1 <- tbl_df(test_1) # tablulate as datafarme 

df - это символьный объект с 3 строковыми значениями:

df <- c("Work hard.", 
        "Show my sadness.", 
        "Like to watch children open presents.")

ниже - функция, которая принимает каждый элемент df, находит его соответствие в test_1 и выводит соответствующие индексы строк из test_1

j <- lapply(df, function(p) {
grep(pattern = p, test_1[ , 1])})
j

# Output
[[1]]
[1] 2 3 # as you see it finds two matches. One is the exact match: "Work hard." row index 2. Another one is a larger string that contains wording of the original string: row index 3. But I only want an exact match, i.e. index 2

[[2]]
[1] 5

[[3]]
[1] 1

Что я хочу: один индекс строки для каждого точно подобранного элемента

[[1]]
[1] 2 

[[2]]
[1] 5

[[3]]
[1] 1

1 Ответ

1 голос
/ 15 мая 2019

Таким образом, используя lapply и grep, вы можете использовать следующий код:

lapply(df, function(z) grep(paste0("^",z,"$"), test_1))

Результаты:

[[1]]
[1] 2

[[2]]
[1] 5

[[3]]
[1] 1

Это работает с использованием якорей.^ - это якорь для начала строки, а $ - это якорь для конца строки.Использование paste0 объединяет якоря с интересующей строкой в ​​df для создания следующего:

[1] "^Work hard.$"                            "^Show my sadness.$"                      "^Like to watch children open presents.$"

и выполняет поиск ТОЧНОЙ целой строки, ограничивая поле поиска тем, что находится между ^ и$.

...