OP的需求是要在过滤时保持未被过滤掉的重复词的频率,这一需求颇具挑战性。无论是通过列表推导还是对列表进行深复制并遍历移除集合以从列表中移除所有实例,都很容易在过滤过程中保留重复词。不过,现有的答案并没有涵盖第二种方法。
但这里我想探讨的是保留词频问题:
存在两种方法:
每个保留词相对于其他保留词的相对频率。现有答案已经提供了对此的解决方案。
每个保留词相对于原始词序列中的频率,即考虑已经被过滤掉的词。在OP的例子中,经过过滤后的词序列是['account','follow' ,'follow','account']
,每个词的频率都是0.5。这个值满足了第一种相对频率解释,即两个词之间的频率相等。但在原始词序列中,这两个词的频率实际上是0.25。如果我们希望保持这个特定的频率值,就应采用第二种解释。
我们希望过滤掉某些词,但同时也要保留被移除词的信息。一种方法是将不需要的词替换为表示其存在的标记。在这个例子中,我将使用标记<UNK>
:
from collections import Counter
tokens=['hi','hi','account','is','follow' ,'follow','account','delhi']
counts = Counter(tokens)
print(counts)
# Counter({'hi': 2, 'account': 2, 'follow': 2, 'is': 1, 'delhi': 1})
# 定义要移除的词集合
stopwords = {'a', 'an', 'is', 'the', 'am', 'hi'}
city = {'london', 'phnom penh', 'beijing', 'paris', 'delhi'}
country = {'india', 'new zealand', 'bhutan', 'laos'}
firstname = {'santosh', 'sanjay', 'sunil', 'khanh', 'lan'}
lastname = {'chen', 'wu', 'zhao', 'laurent', 'moreau'}
otherword = {'vortex'}
# 将上述集合合并
to_remove = stopwords.union(city, country, firstname, lastname, otherword)
# 过滤词
filtered_tokens = tokens[:]
for i in range(len(filtered_tokens)):
if filtered_tokens[i] in to_remove:
filtered_tokens[i] = "<UNK>"
print(filtered_tokens)
# ['<UNK>', '<UNK>', 'account', '<UNK>', 'follow', 'follow', 'account', '<UNK>']
# 统计过滤后的词频
filtered_counts = Counter(filtered_tokens)
print(filtered_counts)
# Counter({'<UNK>': 4, 'account': 2, 'follow': 2})
# 计算归一化频率
def normalised_counter(counter):
total_word_count = sum(counter.values(), 0.0)
for key in counter:
counter[key] /= total_word_count
return counter
print(normalised_counter(counts))
# Counter({'hi': 0.25, 'account': 0.25, 'follow': 0.25, 'is': 0.125, 'delhi': 0.125})
print(normalised_counter(filtered_counts))
# Counter({'<UNK>': 0.5, 'account': 0.25, 'follow': 0.25})
# 在后续使用`filtered_tokens`进行处理时,可以根据任务需求选择是否移除`<UNK>`标记。
补充说明:
如果你希望根据第一种解释创建一个过滤后的列表,但希望使用list.remove()
而非列表推导式:
filtered_token = token[:]
for item in list(to_remove):
try:
while item in filtered_token:
filtered_token.remove(item)
except ValueError:
pass