我有一个包含“clear_message”列的数据框,我创建了一个列来计算每行中的所有单词。
history['word_count'] = history.clear_message.apply(lambda x: Counter(x.split(' ')))
例如,如果行消息是:
Hello my name is Hello
那么他所在行的计数器将是 Counter({'Hello': 2, 'is': 1, 'my': 1, 'name': 1})
问题
我的文本中有表情符号,我还想要一个表情符号计数器。
例如:
test = '👹👹👹👹👹here sasdsa'
test_counter = Counter(test.split(' '))
输出为:
Counter({'sasdsa': 1, '👹👹👹👹👹here': 1})
但我想要:
Counter({'sasdsa': 1, '👹': 5, 'here':1})
显然问题是我正在使用
split(' ')
。
我的想法:
在表情符号前后添加一个空格。喜欢:
test = '👹 👹 👹 👹 👹 here sasdsa'
然后使用split,就可以了。
i
是表情符号,那么 if i in emoji.UNICODE_EMOJI
将返回 true(emoji
包)。我认为你在每个表情符号后面添加一个空格的想法是一个好方法。如果表情符号和下一个字符之间已经有空格,您还需要去除空格,但这很简单。比如:
def emoji_splitter(text):
new_string = ""
for char in text:
if char in emoji.UNICODE_EMOJI:
new_string += " {} ".format(char)
else:
new_string += char
return [v for v in map(lambda x: x.strip(), new_string.split(" ")) if v != ""]
也许您可以通过使用滑动窗口来检查表情符号后面的空格并仅在必要时添加空格来改进这一点,但这会假设只有一个空格,因为此解决方案应考虑表情符号之间的 0 到 n 个空格。
@con-- 答案有一些问题,所以我修复了它。
def emoji_splitter(text):
new_string = ""
text = text.lstrip()
if text:
new_string += text[0] + " "
for char in ' '.join(text[1:].split()):
new_string += char
if char in emoji.UNICODE_EMOJI:
new_string = new_string + " "
return list(map(lambda x: x.strip(), new_string.split()))
示例:
emoji_splitter(' a👹👹👹 ads')
Out[7]: ['a', '👹', '👹', '👹', 'ads']
我想我应该重新审视这个问题,使用具有更复杂表情符号字形的字符串。
如果我们采用字符串
' a👹👹👹 ads👨👨👧 bs🇦🇺'
,将返回两个较旧的答案:['a', '👹', '👹', '👹', 'ads', '👨', '\u200d', '👨', '\u200d', '👧', 'bs🇦🇺']
和['a', '👹', '👹', '👹', 'ads👨', '\u200d👨', '\u200d👧', 'bs🇦🇺']
。
两种解决方案都可以处理简单的表情符号,但无法处理更复杂的表情符号字素。
下面我将使用 regex 模块而不是 re 模块来使用一些 Unicode 正则表达式。
我将处理分为三个离散函数,因此更容易理解。
split_emoji()
将把表情符号子串分割成单独的字素。因此 👹👹👹 被分成三部分,👨u200d👨u200d👧 仍然作为一项,🇦🇺 也是如此。
prep_string()
将在字母序列周围添加额外的空格,然后分割表情符号字素,返回一个字符串。
count_elements()
将调用 prep_string,将结果字符串拆分为一个或多个空白字符,然后对元素进行计数。
import regex
from collections import Counter
def split_emoji(e):
if regex.match(r'\p{Emoji}+', e):
return ' '.join(regex.findall(r'\X', e))
return e
def prep_string(text):
text = regex.sub(r'(\p{L}+)', r" \1 ", text)
items = [split_emoji(substr) for substr in text.split()]
return " ".join(items)
def count_elements(text):
return Counter(regex.split(r'\s+', prep_string(text)))
s = ' a👹👹👹 ads👨👨👧 bs🇦🇺'
count_elements(s)
# Counter({'👹': 3, 'a': 1, 'ads': 1, '👨\u200d👨\u200d👧': 1, 'bs': 1, '🇦🇺': 1})
还可以纳入进一步的改进和边缘情况,例如在标点符号和表情符号之间注入空格,或剥离标点符号。