#python #regex #pandas #dictionary
#питон #регулярное выражение #панды #словарь #python #pandas
Вопрос:
Мне интересно, мог бы кто-нибудь в сообществе помочь со следующим:
Стремитесь к замене подстрок регулярным выражением в фрейме данных pandas (на основе словаря, который я передаю в качестве аргумента). Хотя замена ключа: значения должна выполняться только в том случае, если ключ dict найден как отдельная подстрока (не как часть слова). Под автономной подстрокой я подразумеваю, что она начинается после пробела
e.x:
mapping = {
"sweatshirt":"sweat_shirt",
"sweat shirt":"sweat_shirt",
"shirt":"shirts"
}
df = pd.DataFrame([
["men sweatshirt"]
["men sweat shirt"]
["yellow shirt"]
])
df = df.replace(mapping,regex=True)
ожидаемый результат:
подстрока «рубашка» в свитшоте НЕ должна заменяться на «рубашки», поскольку значение является частью другой строки, не являющейся автономным значением ( b)
ПРИМЕЧАНИЕ: словарь, который я передаю, довольно длинный, поэтому в идеале есть способ передать автономное требование ( b) как часть dict, на который я передаю df.replace(dict, regex=True)
Заранее спасибо
Комментарии:
1. Помимо включения пробелов в сопоставление используйте df = df.apply(лямбда x: ‘ ‘ x, ось =1).заменить (сопоставление, регулярное выражение = True).ID.str.strip()
Ответ №1:
Вы можете использовать
df[0].str.replace(fr"b(?:{'|'.join([x for x in mapping])})b", lambda x: mapping[x.group()])
Регулярное выражение будет выглядеть как b(?:sweatshirt|shirt)b
, оно будет соответствовать sweatshirt
или shirt
как целые слова. Совпадение будет передано в лямбда-выражение, и соответствующее значение будет извлечено с помощью mapping[x.group()]
.
Обновление условия поиска из нескольких слов
Поскольку у вас могут быть многословные термины для поиска в mapping
ключах, вы должны убедиться, что самые длинные условия поиска идут первыми в группе чередования. То есть, b(?:abc def|abc)b
и не b(?:abc|abc def)b
.
import pandas as pd
mapping = {
"sweat shirt": "sweat_shirt",
"shirt": "shirts"
}
df = pd.DataFrame([
["men sweatshirt"],
["men sweat shirt"]
])
rx = fr"b(?:{'|'.join(sorted([x for x in mapping],key=len,reverse=True))})b"
df[0].str.replace(rx, lambda x: mapping[x.group()])
Вывод:
0 men sweatshirt
1 men sweat_shirt
Name: 0, dtype: object
Комментарии:
1. интересно, учитывает ли ваш приведенный выше код также подстроки, которые находятся в самом начале значения ячейки, например, ^ рубашка 123? Спасибо
2. @Mirko Да,
b
, когда за ним следует символ «word» (цифра, буква или_
), также совпадает в начале строки.3. есть последний вопрос (извините, что беспокою Виктора). было несколько крайних случаев, когда repl. не работал. придерживаться ex. Я дал в первоначальном сообщении. допустим, идентификатор имеет df со значением
men sweat shirt
и следующим отображением"sweat shirt: "sweat_shirt", "shirt": "shirts"
. Я не уверен, действительно ли вступят в силу key1: value1 или key2: value2. кажется, в 9/10 случаях key1:value1 заменяется, но не всегда. вы можете определить, обрабатывается ли dict, используемый в сопоставлении, сверху вниз, чтобы я мог добавить эти ключи с пробелом перед этими ключами без? есть другие идеи?
Ответ №2:
Включите пробел в свой шаблон! 🙂
mapping = {
" sweatshirt":" sweat_shirt",
" shirt":" shirts"
}
df = ([
["men sweatshirt"]
])
df = df.replace(mapping,regex=True)
Комментарии:
1. Это не заменит строку, если строка для замены находится в начале.
Ответ №3:
Попробуйте этот код-
mapping = {
" sweatshirt":" sweat_shirt",
" shirt":" shirts"
}
import pandas as pd
df = pd.DataFrame ({'ID':["men sweatshirt", "black shirt"]}
)
df = df.apply(lambda x: ' ' x, axis=1).replace(mapping,regex=True).ID.str.strip()
print(df)