在Python Pandas中标记项目

时间:2017-07-14 10:39:37

标签: python pandas

我有一个数据框如下:

                Id     Type       
0              14035   A          
1              14035   B      
2              14035   C                         
3              24259   A    
4              24259   B     

我正在尝试使用pandas python进行一些分类,如果它包含ABC / BAC / CBA排列,则将其分类为类别1.如果它仅包含AB / BA,则将其归类为类别2.

                Id     Classification
0              14035   Category 1                                  
3              24259   Category 2 

我想过使用一个小组并放入一个小组但是我不确定要去做它,因为我还是Python的新手。

任何帮助?

谢谢!

5 个答案:

答案 0 :(得分:2)

在这里,您可以使用groupby

df.groupby("Id")["Type"].apply(lambda x: "Category 1" if x.str.cat() == "ABC" else "Category 2")

输出:

Id
14035    Category 1
24259    Category 2
Name: Type, dtype: object

答案 1 :(得分:1)

虽然之前的解决方案往往有效,但我担心使用的字符串连接。

此类字符串连接无法对以下情况的ID进行分类:

  1. 如果字符以未排序的方式连接,则后面的逻辑将无法对ID进行分类。 ie: ('BAC' != 'ABC')

  2. 如果该组包含其他类型,例如“ABCD”,则字符串连接也无法正确分类组ie: ('ABCD' != 'ABC')

  3. 我宁愿选择更长更安全的解决方案:

    import pandas as pd
    import numpy as np
    
    # Construct sample dataframe 
    df = pd.DataFrame()
    df['Id'] = ['14035', '14035', '14035', '24259', '24259', ]
    df['Type'] = ['A', 'B', 'C', 'A', 'B', ]
    
    
    # Define classification logic
    def classification_logic(list_of_types):
        if set(['A', 'B', 'C']) <= set(list_of_types):
            return 1
        if set(['A', 'B']) <= set(list_of_types):
            return 2
        return np.nan
    
    # Apply to groups
    df.groupby('Id').aggregate(classification_logic)
    #        Type
    # Id         
    # 14035     1
    # 24259     2
    

答案 2 :(得分:0)

这是一个相当普遍的解决方案:

# Find which elements are present in each id
elements_in_id = df.groupby('Id').apply(lambda x: x.astype(str).sum())['Type']

categories = {"ABC" : 'Category 1', "AB" : 'Category 2'}

# Assign category if present, otherwise assign "Not Classified"
# Assume that the keys in categories contain letters sorted alphabetically
result = elements_in_id.map(lambda x: categories.get(''.join(sorted(x)), 'Not Classified'))

这给出了预期的输出:

Id
14035    Category 1
24259    Category 2

答案 3 :(得分:0)

@CarlesMitjans's answer的启发,这里有一个优化版本:

In [66]: df.groupby('Id')['Type'] \
    ...:   .agg(lambda x: 'Cat 1' if 'ABC' in ''.join(x.sort_values()) else 'Cat 2') \
    ...:   .reset_index(name='Cat')
    ...:
Out[66]:
      Id    Cat
0  14035  Cat 1
1  24259  Cat 2

答案 4 :(得分:0)

我会使用set比较来使其无论顺序如何都能正常工作

In [976]: df.groupby("Id")["Type"].apply(
     ...:    lambda x: 'Cat 1' if set(x) == set('ABC') else
     ...:              'Cat 2' if set(x) == set('AB') else
     ...:              'Cat X')
Out[976]:
Id
14035    Cat 1
24259    Cat 2
Name: Type, dtype: object