#python #pandas #dataframe
Вопрос:
Я только что обозначил столбец в фрейме данных с помощью nltk.word_tokenize. Эта колонка теперь выглядит так
df.tokenized
> 0 [apple, hi, dog, boy, why...]
> 1 [table, hey, girl, cat, dog, 2, 3...
Для каждой строки мне нужно получить 2 слова до и 2 слова после слова «собака». Я хочу поместить все это в другой столбец в том же фрейме данных. Результат, который я ожидаю, будет примерно таким:
df.tokenized_part2
> 0 [apple, hi, dog, boy, why]
> 1 [girl, cat, dog, 2, 3]
Поэтому мне нужно создать этот столбец с маркировкой _part2.
Если вам нужна эта информация: маркированный объект
Кто-нибудь знает, как это сделать?
Комментарии:
1. может быть, вам следует повторить каждую строку и найти позицию в строке, а затем получить
[pos-2:pos 2]
2. что делать, если в списке нет собаки?
Ответ №1:
Вы можете использовать apply()
функцию для запуска в каждой ячейке столбца, и эта функция может получить позицию dog
в списке и вернуться [pos-2:pos 3]
import pandas as pd
df = pd.DataFrame({
"tokenized": [
['apple', 'hi', 'dog', 'boy', 'why', 'other'],
['table', 'hey', 'girl', 'cat', 'dog', '2', '3'],
['A', 'B', 'C'],
]
})
def process(words):
#print(words)
if 'dog' in words:
pos = words.index('dog')
return words[pos-2:pos 3]
else:
#return words
return []
df["tokenized_2"] = df["tokenized"].apply(process)
print(df)
Результат:
tokenized tokenized_2
0 [apple, hi, dog, boy, why, other] [apple, hi, dog, boy, why]
1 [table, hey, girl, cat, dog, 2, 3] [girl, cat, dog, 2, 3]
2 [A, B, C] []
Редактировать:
Чтобы сделать его более универсальным, он мог бы получить dog
(или другое слово) в качестве параметра, а затем вы бы запустили его с lambda
(или partial
)
import pandas as pd
df = pd.DataFrame({
"tokenized": [
['apple', 'hi', 'dog', 'boy', 'why', 'other'],
['table', 'hey', 'girl', 'cat', 'dog', '2', '3'],
['A', 'B', 'C'],
]
})
def process(words, search):
#print(words)
if search in words:
pos = words.index(search)
return words[pos-2:pos 3]
else:
#return words
return []
df["tokenized_dog"] = df["tokenized"].apply(lambda words:process(words, 'dog'))
df["tokenized_cat"] = df["tokenized"].apply(lambda words:process(words, 'cat'))
print(df[["tokenized_dog", "tokenized_cat"]])
Результат:
tokenized_dog tokenized_cat
0 [apple, hi, dog, boy, why] []
1 [girl, cat, dog, 2, 3] [hey, girl, cat, dog, 2]
2 [] []
Комментарии:
1. Идеально! Чтобы сделать его еще более универсальным: list_words = [‘кошка’, ‘собака’, ‘птица’] для элемента в list_words: df[‘col’ ‘_’ str(элемент)] = df[«маркированный»].применить(лямбда-слова:процесс(слова, элемент))
Ответ №2:
Один из способов сделать это-использовать apply с lambda, например
lambda x: [i for ix,i in enumerate(x) if ix in range([idx for idx,it in x if it=='dog'][0]-2,[idx for idx,it in x if it=='dog'][0] 2)]
Но это дорого с точки зрения вычислений, подвержено ошибкам и, вероятно, излишне сложно.
Комментарии:
1. это совершенно нечитабельно или понятно
2. @gold_cy это буквально
process
из другого ответа как понимание вложенного списка внутри лямбды. Или, скорее, поскольку они ответили после меня, их функция-понимание моего вложенного списка, растянутого на ненужное количество символов. Если кому-то нужно объяснить вам, что заполнители в понятиях (например, циклах) и лямбда-выражениях (например, функциях) не обязательно должны быть значимыми, чтобы быть понятными, вам следует подумать о том, где корень этой проблемы. Им нужен был рабочий код. Код работает.3. жертвовать строками кода, чтобы сделать его читабельным, всегда считается правильным подходом. дополнительные строки кода не означают дополнительной обработки. в таком языке, как Python, читабельность имеет первостепенное значение и то, что она превосходит ее.
4. О. Я думал, что это удивительный ассортимент библиотек, динамическая типизация и способность невероятно эффективно решать проблемы в коде вместо того, чтобы набирать множество и множество для простых задач.
5. Кстати, теперь я собираюсь понять ваш первый комментарий программно, а не в смысле естественного языка. Спасибо, что сказали, что мой код понятен @gold_cy.