2015-04-06 2 views
1

Я ищу способ сопоставить один столбец с другим (но с учетом границ слов). Если совпадения нет, удалите всю строку. Пример: в случае, если нет точного соответствия токена (примечание banana != bananas) между NODE и SENTENCE (dataframe), удалите строку. Другими словами: if (\b.+\b) in NODE can't be found in SENTENCE, remove the row.Если значение в столбце A не найдено в столбце B, удалите строку в R

NODE  |  SENTENCE 
----------------------------------------------------------- 
banana   I am a banana and I like it 
banana   We ate two bananas yesterday 
banana   I ate a banana two days ago 
coffee   Would you like a cup of coffee? 
coffee   We went by that new coffeeshop the other day 

Результат

NODE  |  SENTENCE 
----------------------------------------------------------- 
banana   I am a banana and I like it 
banana   I ate a banana two days ago 
coffee   Would you like a cup of coffee? 

Я думал использовать ifelse, но я не совсем уверен, как применить это.

ifelse(df$NODE==df$SENTENCE,NA,???) 

EDIT: учитывая ответ NICO, это не работает для меня. Однако используется \\s вместо \\b работ. Разве - не подразумевает границы слова? Вниз стороной этого является то, что он не будет обнаружить, когда узел находится в начале или в конце предложения (поскольку в этом случае не предшествует или после пространственного характера) .:

r <- c("Het label heeft ook verantwoordelijkheidsgevoel: aan de lancering van B-Camp wordt een Goodwill Project gekoppeld, een fonds dat zijn financiële bijdrage wil leveren ter bestrijding van de aids-plaag.", 
    "B-Camp koos voor de opvang en verzorging van kinderen besmet met het aids-virus.", 
    "Hij zei dat hij aids had.", 
    "Aids in het land?") 
s <- c("aids","aids","aids","aids") 
d1 <- data.frame(node = s,sentence=r) 

matches <- mapply(grep, paste0("(?i)\\s", d1$node, "\\s"), d1$sentence) 
to.keep <- sapply(matches, length)>0 
(d1 <- d1[to.keep,]) 

ВЫВОД

node sentence 
--------------------------------- 
aids Hij zei dat hij aids had.  

ЗАПЛАНИРОВАННЫЕ

node sentence 
---------------- 
aids Hij zei dat hij aids had. 
aids Aids in het land? 
+0

@BillWoodger Поскольку только две колонки и пять строк, я не совсем уверен, что вы имеете в виду. –

+0

Ах. Я думал, что я, я, банан и т. Д., Были «колоннами». Значит, вам просто нужно знать, что второе содержит первое, на основе слов? –

+0

@BillWoodger NODE и SENTENCE - это два столбца в 'df'. Да. Мне нужно сохранить строки, в которых столбец предложения содержит точно значение узла. –

ответ

2

Вот возможное Векторизованным решение с использованием stringi пакета (хотя, возможно, чрезмерно сложно ...)

library(stringi) 
indx <- as.logical(rowSums(with(df, 
           NODE == stri_split_regex(SENTENCE, 
           "[[:punct:] ]", simplify = TRUE)))) 
df[indx, ] 
# NODE      SENTENCE 
# 1 banana  I am a banana and I like it 
# 3 banana  I ate a banana two days ago 
# 4 coffee Would you like a cup of coffee? 

Идея заключается в том, чтобы новообращенный SENTENCE в матрицу слов, разделенных пунктуацией или пробелом, а затем просто найдите, если есть точное совпадение, используя в NODE с помощью оператора ==.


Edit в новых наборов данных

indx <- as.logical(rowSums(with(d1, 
        node == tolower(stri_split_regex(sentence, "[ :?.,]", 
        simplify = TRUE))))) 

d1[indx, ] 
# node     sentence 
# 3 aids Hij zei dat hij aids had. 
# 4 aids   Aids in het land? 

Edit # 2 (пытаясь сделать его менее "ресурсоемких")

myfunc <- function(x, y) any(x == y) 
indx <- with(d1, mapply(myfunc, node, stri_split_regex(tolower(sentence), "[ :?.,]"))) 
d1[indx, ] 
# node     sentence 
# 3 aids Hij zei dat hij aids had. 
# 4 aids   Aids in het land? 
+0

Не видел ваше редактирование сначала. Кажется, это работает, хорошо. Не могли бы вы объяснить первую часть 'indx'? Что делает rowSums? И «упростить»? –

+0

Применение этого на большом наборе кажется довольно ресурсоемким, хотя (просто для будущих читателей). –

+1

'stri_split_regex' создает матрицу (таким образом,' simplify = TRUE' - так что это не будет список), а затем я просто использую 'rowSums', чтобы суммировать совпадения в строке. Если сумма больше, чем '0',' as.logical' преобразует ее в 'TRUE'. Это даст мне индекс «TRUE/FALSE» для каждой строки. –

2

Это должно работать:

# Use grep to match \bNODE\b in SENTENCE row by row 
matches <- mapply(grep, paste0("\\b", df$NODE, "\\b"), df$SENTENCE) 
# Find rows with at least one match 
to.keep <- sapply(matches, length)>=1 
# Keep those 
df[to.keep,] 

Обратите внимание, что GREP возвращает logical(0), если совпадение не найдено, поэтому я использую length для проверки совпадений. Вызов sapply приведет к вектору, содержащему количество совпадений для каждого слова.

EDIT: после редактирования вопроса

вы можете использовать ignore.case=T сделать спички нечувствительны к регистру. Я обновил регулярное выражение, чтобы принять во внимание границы предложений. Там должен быть более простым способом, хотя ...

matches <- mapply(grep, paste0("\\s", d1$node, "\\s|^", d1$node, 
      "|", d1$node, "$"), d1$sentence, ignore.case=TRUE) 
+0

@Thomas hmmmm 'sapply' не возвращает логический вектор в этом случае – nico

+0

@BillWoodger нет причин, я просто случайно написал, что ...,> 0 также работает – nico

+0

Спасибо. Просто интересуюсь. Очистка ... –

Смежные вопросы