Pandas`groupby`似乎只对第一组应用功能

时间:2017-02-27 20:37:22

标签: python pandas

我有一个带有词性标签的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

似乎只是将该功能应用于第一组。怎么样?

1 个答案:

答案 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