Мне нужна перечисляющая функция регулярного выражения, которая идентифицирует экземпляры в строке, когда «Слово 1» находится в пределах N # слов «Слова 2».
Например, вот мой фрейм данных и цель:
Ввод данных Pandas
data = [['ABC123', 'This is the first example sentence the end of
sentence one'], ['ABC456', 'This is the second example sentence one more
sentence to come'], ['ABC789', 'There are no more example sentences']]
df = pd.DataFrame(data, columns=['Record ID', 'String'])
print(df)
Record ID | String
----------|-----------------------
ABC123 | This is the first example sentence the end of sentence one
ABC456 | This is the second example sentence one more sentence to come
ABC789 | There are no more example sentences
Слово 1 = «предложение» Слово 2 = 'то' В пределах N# слов (смещенных) = 3
Желаемый вывод кадра данных
output_data = [['ABC123', 3], ['ABC456', 1], ['ABC789', 0]]
df = pd.DataFrame(output_data, columns=['Record ID', 'Occurrences Identified'])
print(df)
Record ID | Occurrences Identified
----------|-----------------------
ABC123 | 3
ABC456 | 1
ABC789 | 0
Я думаю, что часть регулярных выражений примет общую форму этого, но я не уверен, как применить ее к моему варианту использования здесь, в Python, и... я не уверен, с чего начать с функцией перечисления.
\b(?:'sentence'\W+(?:\w+\W+){0,3}?'the'|'the'\W+(?:\w+\W+){0,3}?'sentence')\b
Меня также интересуют более простые решения без регулярных выражений, если таковые имеются.
Data = pd.read_sql(query, engine)
# Convert to Pandas DataFrame
nearwordDF = pd.DataFrame(Data)
# Remove non-alpha characters and make all lowercase
nearwordDF['text'] = nearwordDF['text'].str.replace(',', ' ')
nearwordDF['text'] = nearwordDF['text'].str.replace('.', '')
nearwordDF['text'] = nearwordDF['text'].str.replace('?', '')
nearwordDF['text'] = nearwordDF['text'].str.replace('\r', '')
nearwordDF['text'] = nearwordDF['text'].str.lower()
print(nearwordDF)
--------------------------
id text
ABC123 how much money do i have in my money account
ABC456 where is my money
ABC789 hello how are you today what is your name
DEF123 my money market fund is my only money of my account
import re
import pandas as pd
output = []
for i in nearwordDF:
regex = r'(?:my(?:\s\w+){0,2})\s(?=money)|(?:money(?:\s\w+){0,2})\s(?=my)'
nearwordDF = re.findall(regex, i[1])
output.append([i[0], len(nearwordDF)])
df = pd.DataFrame(output, columns=['Record ID', 'Occurrences'])
print(df)
-----------------------------------
# Output
Record ID Occurrences
i 0
t 0
@ Рамеш, конечно, без проблем. Вот визуальное объяснение того, почему для каждой записи: imgur.com/hMpHIBn
This is the first example sentence the end of sentence one
в этом тексте всего 2 вхождения the
и sentence
это правильно?
@Ramesh Есть три случая: (1) «первое примерное предложение», (2) «предложение», (3) «конец предложения». (1) и (2) перекрываются.
@ Рамеш да, утвердительно. Есть ли способ закрыть этот вопрос как «решенный» или я должен просто поделиться с вами предпочтительным решением в сообщении?
Если вопрос решен, то «примите» ответ с решением. Если ни один из существующих ответов не является правильным или достаточным, напишите полный ответ и примите его. См. страницы Справочного центра для получения дополнительной информации о принятии ответов.
Возможно, регулярное выражение здесь не подходит.
Если вы разделите свою входную строку на список, вы сможете найти индексы слов 1 и 2 и вычислить, насколько далеко они друг от друга:
string = 'This is the first example sentence the end of sentence one'
string_list = string.split(' ')
indices_word_1 = [i for i, x in enumerate(string_list) if x == "sentence"]
indices_word_2 = [i for i, x in enumerate(string_list) if x == "the"]
result = 0
for i in indices_word_1:
for j in indices_word_2:
_distance = abs(i - j)
if _distance <= 3:
result += 1
В этом случае результат равен 3.
@tshobe, вот один из способов реализовать мое предложение:
import pandas
def check_occurences(string, word_1='sentence', word_2='the', allowed_distance=3):
string_list = string.split(' ')
indices_word_1 = [i for i, x in enumerate(string_list) if x == word_1]
indices_word_2 = [i for i, x in enumerate(string_list) if x == word_2]
result = 0
for i in indices_word_1:
for j in indices_word_2:
_distance = abs(i - j)
if _distance <= allowed_distance:
result += 1
return result
def main():
data = [['ABC123', 'This is the first example sentence the end of sentence one'],
['ABC456', 'This is the second example sentence one more sentence to come'],
['ABC789', 'There are no more example sentences']]
df = pandas.DataFrame(data, columns=['Record ID', 'String'])
results_df = pandas.DataFrame(columns=['Record ID', 'Occurrences'])
results_df['Record ID'] = df['Record ID']
results_df['Occurrences'] = df['String'].apply(lambda x: check_occurences(x))
print(results_df)
if __name__ == "__main__":
main()
Это хорошее решение с использованием перечисления и индекса :).
Как использовать это в уже существующем кадре данных Pandas с определенным столбцом для строки? Когда я запускаю это, ничего не происходит, ничего не возвращается. Я использую это в начале? string_list = pandasDF['Имя столбца'].str.split(' ') Кроме того, как мне получить вывод в нужном мне формате, где это новый фрейм данных с двумя столбцами (идентификатор записи и идентифицированные вхождения)?
Мой ответ показывает логический способ решения вашей проблемы, но на самом деле он не показывает, как ее реализовать. Я попытаюсь отредактировать свой комментарий с реализацией.
@tshobe, пожалуйста, посмотрите мое решение, я добавил реализацию
Я думаю, вы были очень близки к разгадке. ' в вашем регулярном выражении соответствует буквальным апострофам. Но вы не хотите сопоставлять апострофы. Если вы удалите их, вы получите правильный шаблон:
>>> re.compile(r'\b(?:sentence\W+(?:\w+\W+){0,3}?the|the\W+(?:\w+\W+){0,3}?sentence)\b', re.I).finditer("This is the first example sentence the end of sentence one")
[<_sre.SRE_Match object; span=(8, 34), match='the first example sentence'>,
<_sre.SRE_Match object; span=(35, 54), match='the end of sentence'>]
Обратите внимание, что это находит только два вхождения, потому что совпадения регулярных выражений не перекрываются. Если вам нужны перекрывающиеся результаты, вам, вероятно, лучше использовать другое решение.
Вы можете использовать положительный взгляд вперед (?=), чтобы подтвердить слово sentence.
import re
import pandas as pd
data = [['ABC123', 'This is the first example sentence the end of sentence one'],
['ABC456', 'This is the second example sentence one more sentence to come'],
['ABC789', 'There are no more example sentences']]
output = []
for i in data:
regex = r'(?:the(?:\s\w+){0,2})\s(?=sentence)|(?:sentence(?:\s\w+){0,2})\s(?=the)'
data = re.findall(regex, i[1])
output.append([i[0], len(data)])
print(output)
df = pd.DataFrame(output, columns=['Record ID', 'Occurrences Identified'])
print(df)
Выход
[['ABC123', 3], ['ABC456', 1], ['ABC789', 0]]
Record ID Occurrences Identified
0 ABC123 3
1 ABC456 1
2 ABC789 0
Это здорово, но как и где именно мне вставить уже созданный ранее существующий фреймворк данных? Мои данные уже в формате Pandas Dataframe и содержат тысячи строк (из запроса SQL). Когда я пытаюсь подключить его к вашему фрагменту кода, он просто получает сообщения об ошибках, например, длина не соответствует или «Серия» не может быть вызвана, или вывод просто пуст.
Если регулярное выражение работает, вы можете добавить его в предложение выбора sql вместо того, чтобы запрашивать ваши данные, а затем запускать регулярное выражение на вашем df из python.
Я согласен, но только в образовательных целях, я все же хотел бы знать, как запустить этот код на основе уже существующего фрейма данных, если вы не возражаете объяснить эту часть. Я буду использовать его позже для других функций.
Можете ли вы добавить код, используя приведенное выше регулярное выражение, чтобы я мог проверить сообщения об ошибках.
Можете ли вы объяснить, почему ABC123 получил 3 вхождения?