我有一个带有词性标签的pandas DataFrame,我正在尝试构建一个词性标注器。它看起来像这样。
silly_df = pd.DataFrame.from_dict({"INDEX":[1, 1, 1, 2, 2, 2, 2, 2],
"LABEL": ['X', 'Y', 'Z', 'Z', 'Z', 'X', 'X', 'Y']})
看起来像:
INDEX LABEL
0 1 X
1 1 Y
2 1 Z
3 2 Z
4 2 Z
5 2 X
6 2 X
7 2 Y
INDEX
列将标记组合在一起,每个标记都有一个标签。
但是,我想修改标签以提高模型的性能。我想将每个"Z"
转换为"B-Z"
或"I-Z"
,其中"B-Z"
表示我们处于 b 的某个位置(可能) length-1)Z
的字符串,而“I-Z
”表示我们在 i nside(或可能是结尾)的一个(长度> 1) )"Z"
的字符串。所有这些转换都应该在索引中进行,以便所需的输出为
INDEX LABEL NEW_LABEL
0 1 X X
1 1 Y Y
2 1 Z B_Z
3 2 Z B_Z
4 2 Z I_Z
5 2 X X
6 2 X X
7 2 Y Y
我编写了一些代码,可以在一个索引级别的单个标签列表上执行此重新标记:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def add_b_i(beg, inside, match, labels):
for i, (s, t) in enumerate(pairwise(labels)):
if t == match:
if s != match:
labels[i+1] = beg
else:
labels[i+1] = inside
return labels
现在我希望这可以分组应用这个功能,但是当我尝试时,我得到:
silly_df.groupby('INDEX')['LABEL'].transform(lambda x: add_b_i('B-Z', 'I-Z', 'Z', x))
输出:
0 X
1 Y
2 B-Z
3 Z
4 Z
5 X
6 X
7 Y
似乎只是将该功能应用于第一组。怎么样?
答案 0 :(得分:1)
你可以尝试这种矢量化方法,(通常你不需要枚举一个Series对象,因为它已包含索引):
import pandas as pd
import numpy as np
def add_b_i(beg, inside, match, labels):
match_logic = labels == match
match_count = match_logic.cumsum()
return labels.where(~match_logic,
np.where(match_logic & (match_count == 1), beg, inside))
silly_df.groupby('INDEX')['LABEL'].transform(lambda x: add_b_i('B-Z', 'I-Z', 'Z', x))
#0 X
#1 Y
#2 B-Z
#3 B-Z
#4 I-Z
#5 X
#6 X
#7 Y
#Name: LABEL, dtype: object