【问题标题】:Combine multiple categories into one in Pandas在 Pandas 中将多个类别合二为一
【发布时间】:2019-10-29 18:02:01
【问题描述】:

我有一个数据集,其中有一列包含类别。我想做的是将这些类别组合成新的类别。

我的数据集如下所示(类别列是一个字符串列),我有 160 个类别。

在我的示例中,仅显示了四个类别。

Category  
ZA-01
ZA-01
ZA-01
ZA-01
XA-01
XA-01
XA-01
XA-01
YA-01
YA-01
YA-01
YA-01
WA-01
WA-01
WA-01
WA-01

我想得到的是以下(数据框中行的原始顺序不变,这很重要)

Category     New_Category
ZA-01        A
ZA-01        A
ZA-01        A
ZA-01        A
XA-01        A
XA-01        A
XA-01        A
XA-01        A
YA-01        B
YA-01        B
YA-01        B
YA-01        B
WA-01        B
WA-01        B
WA-01        B
WA-01        B

最简单的方法是使用 if elif 语句,但如果您有 160 个类别,这是一项艰巨的任务,而且很容易出错。

我希望 Python 做的是使用 df.[['categories]].unique() 获取唯一类别,它保留数据框中类别的顺序,然后对 Python 说:group category one (ZA -01) 和两个 (XA-01) 组合成一个名为 A 的新类别,然后将类别三 (YA-01) 和类别四 (WA-01) 组合成一个名为 B 的新类别,以此类推。

在 Python 中有没有不使用 if elif 语句的方法?


-------------------编辑-----------

如果我有的话

Group    Category  
A        ZA-01
A        ZA-01
A        ZA-01
A        ZA-01
A        XA-01
A        XA-01
A        XA-01
A        XA-01
A        ZZ-12      
A        ZX-11      
B        YA-01
B        YA-01
B        YA-01
B        YA-01
B        WA-01
B        WA-01
B        WA-01
B        WA-01
B        ZZ-01      
B        ZZ-99      
B        ZZ-99      
B        AA-01 

我想在一个组中组合两个类别(所以在 A 中我想组合两个类别的组,在 B 中我想组合两个类别等等)。同样,我想保留原始数据框中的行顺序。

所以我想得到

Group    Category   New_Category
A        ZA-01      1
A        ZA-01      1
A        ZA-01      1
A        ZA-01      1
A        XA-01      1
A        XA-01      1
A        XA-01      1
A        XA-01      1
A        ZZ-12      2
A        ZX-11      2   
B        YA-01      3
B        YA-01      3
B        YA-01      3
B        YA-01      3
B        WA-01      3
B        WA-01      3
B        WA-01      3
B        WA-01      3
B        ZZ-01      4
B        ZZ-99      4
B        ZZ-99      4
B        AA-01      5

【问题讨论】:

    标签: pandas categories pandas-groupby


    【解决方案1】:

    修改后的问题

    您不需要 groupby。只需将factorizeGroupCategory 的元组一起使用

    df['New_Category']= (pd.factorize(list(zip(df.Group, df.Category)))[0] // 2) + 1
    
    Out[272]:
       Group Category  New_Category
    0      A    ZA-01             1
    1      A    ZA-01             1
    2      A    ZA-01             1
    3      A    ZA-01             1
    4      A    XA-01             1
    5      A    XA-01             1
    6      A    XA-01             1
    7      A    XA-01             1
    8      A    ZZ-12             2
    9      A    ZX-11             2
    10     B    YA-01             3
    11     B    YA-01             3
    12     B    YA-01             3
    13     B    YA-01             3
    14     B    WA-01             3
    15     B    WA-01             3
    16     B    WA-01             3
    17     B    WA-01             3
    18     B    ZZ-01             4
    19     B    ZZ-99             4
    20     B    ZZ-99             4
    21     B    AA-01             5
    

    原创

    使用 pd.factorize 和 floor div 2

    df['new_category'] = pd.factorize(df.Category)[0] // 2
    
    Out[154]:
       Category  new_category
    0     ZA-01             0
    1     ZA-01             0
    2     ZA-01             0
    3     ZA-01             0
    4     XA-01             0
    5     XA-01             0
    6     XA-01             0
    7     XA-01             0
    8     YA-01             1
    9     YA-01             1
    10    YA-01             1
    11    YA-01             1
    12    WA-01             1
    13    WA-01             1
    14    WA-01             1
    15    WA-01             1
    

    在上面有new_category 之后,如果您想映射到您的自定义类别,只需执行这些额外步骤

    cats = np.array(['A', 'B'])
    df['new_category'] = cats[df['new_category']]
    
    Out[163]:
       Category new_category
    0     ZA-01            A
    1     ZA-01            A
    2     ZA-01            A
    3     ZA-01            A
    4     XA-01            A
    5     XA-01            A
    6     XA-01            A
    7     XA-01            A
    8     YA-01            B
    9     YA-01            B
    10    YA-01            B
    11    YA-01            B
    12    WA-01            B
    13    WA-01            B
    14    WA-01            B
    15    WA-01            B
    

    添加@piRSquare 创建字母类别的方法

    from string import ascii_uppercase
    from itertools import product
    import numpy as np
    
    letters = [*ascii_uppercase]
    leading = [''] + letters
    cats = np.array([*map(''.join, product(*[leading] * 3, letters))])
    

    或者

    from string import ascii_uppercase
    from itertools import product
    cats = np.array([*map(''.join, product(['', *ascii_uppercase], ascii_uppercase))])
    cats[df.Category.factorize()[0] // 2]
    
    Out[13]:
    array(['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B',
           'B', 'B', 'B'], dtype='<U2')
    

    【讨论】:

    • 如果我有 159 个类别(数量不等),这也行吗?
    • 不错的一个。 df.Category.factorize() 也可以。 chr 可能很危险,因为这里有 80 个类别。
    • 我会这样做的。你可以得到这样的字母from string import ascii_uppercase; from itertools import product; cats = np.array([*map(''.join, product(['', *ascii_uppercase], ascii_uppercase))])然后使用numpy切片cats[df.Category.factorize()[0] // 2]
    • 对于任意数量的类别gist
    • 不,很遗憾没有。一个组可以有许多类别(均匀和不均匀)。一组可以有 160 个类别(严重)。
    【解决方案2】:

    你可以照你说的用map

    cats = df.Category.unique()
    
    # define new categories
    # replace np.arange(len(cats)) with your category names
    # e.g ['A','B']
    new_cats = np.repeat(np.arange(len(cats)), 2)[:len(cats)]
    
    s = pd.Series(new_cats, index=cats)
    df['New_Cat'] = df['Category'].map(s)
    

    输出:

       Category  New_Cat
    0     ZA-01        0
    1     ZA-01        0
    2     ZA-01        0
    3     ZA-01        0
    4     XA-01        0
    5     XA-01        0
    6     XA-01        0
    7     XA-01        0
    8     YA-01        1
    9     YA-01        1
    10    YA-01        1
    11    YA-01        1
    12    WA-01        1
    13    WA-01        1
    14    WA-01        1
    15    WA-01        1
    

    详情s

    ZA-01    0
    XA-01    0
    YA-01    1
    WA-01    1
    dtype: int32
    

    【讨论】:

    • 如果我有 159 个类别(数量不等),你的方法也行吗?
    • 是的,[:len(cats)] 负责处理。
    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 2019-09-30
    • 2015-12-30
    • 2015-01-08
    • 2021-05-30
    • 1970-01-01
    • 2019-11-06
    相关资源
    最近更新 更多