当类别名称与数据混合时如何提取组类别

Posted

技术标签:

【中文标题】当类别名称与数据混合时如何提取组类别【英文标题】:How to extract group categories when the category names are mixed with the data 【发布时间】:2022-01-11 23:40:16 【问题描述】:

我有以下数据结构。其中类别名称与产品名称混合在一起

df = pd.DataFrame(data='name':['Category A', 'Subcategory A.A', 'Product A', 'Product B', 'Category B', 'Product C'],'values':["", "", 1,2,"", 3])

name                values
Category A  
Subcategory A.A 
Product A           1
Product B           2
Category B  
Product C           3

name 列中没有值的每个条目都是类别名称。

有没有办法将pandas DataFrame 转换成如下结构?

name        values      category
Product A   1           Category A, Subcategory A.A
Product B   2           Category A, Subcategory A.A
Product C   3           Category B

感谢任何帮助。

【问题讨论】:

【参考方案1】:

我不确定是否有一种非常熊猫式的方式来处理这个问题,所以我想出了一个简单的 Python 解决方案:

new_data = 'name':[], 'values': [], 'category': []
lasts = 
for idx, row in df.iterrows():
    tp, val = row['name'].split(' ')
    if row['values'] == '':
        lasts[tp] = val
        # Reset the subcategory if a new category is encountered
        if tp == 'Category' and 'Subcategory' in lasts:
            del lasts['Subcategory']
    else:
        new_data['category'].append(', '.join(f'k v' for k, v in zip(lasts.keys(), lasts.values())))
        for k in row.index:
            new_data[k].append(row[k])
df = pd.DataFrame(new_data)

输出:

>>> df
        name  values                     category
0  Product A       1  Category A, Subcategory A.A
1  Product B       2  Category A, Subcategory A.A
2  Product C       3                   Category B

【讨论】:

【参考方案2】:

使用cumsum为类别块创建自定义分组并使用groupby.apply返回非类别行+新类别列:

# create custom grouping per category block
newgroup = df['values'].eq('') & df['values'].shift().ne('')
groups = newgroup.cumsum()

# given group g, return subframe of non-category rows + category name
def categorize(g):
    is_category = g['values'].eq('')
    category = ', '.join(g.loc[is_category, 'name']) # join category names by comma
    return g.loc[~is_category].assign(category=category) # return non-category rows with new category column

# apply custom function to each group
df.groupby(groups).apply(categorize).droplevel(0)

输出:

        name values                     category
2  Product A      1  Category A, Subcategory A.A
3  Product B      2  Category A, Subcategory A.A
5  Product C      3                   Category B

详情

    当当前values 为空而前一个values 不为空时,每个类别块开始,因此我们可以generate pseudo-groups using cumsum。这里的组显示为一列,仅供视觉参考:

    newgroup = df['values'].eq('') & df['values'].shift().ne('')
    groups = newgroup.cumsum()
    
    #               name  values  groups
    # 0       Category A               1
    # 1  Subcategory A.A               1
    # 2        Product A       1       1
    # 3        Product B       2       1
    # 4       Category B               2
    # 5        Product C       3       2
    

    在每个组中,通过连接所有类别行中的name 来获取类别字符串。那么我们assign新的分类名称后就可以返回非分类的行了:

    def categorize(g):
        is_category = g['values'].eq('')
        category = ', '.join(g.loc[is_category, 'name']) # join category rows by comma
        return g.loc[~is_category].assign(category=category) # return non-category rows with new category column
    

    将此函数传递给groupby.apply:

    df.groupby(groups).apply(categorize).droplevel(0)
    
    #         name values                     category
    # 2  Product A      1  Category A, Subcategory A.A
    # 3  Product B      2  Category A, Subcategory A.A
    # 5  Product C      3                   Category B
    

【讨论】:

太棒了,非常感谢您的详细解释

以上是关于当类别名称与数据混合时如何提取组类别的主要内容,如果未能解决你的问题,请参考以下文章

当标题是键和值的混合时,将数据从 json 附加到表

Firebase 关系删除

phpcms的分类名称和类别名称的调用

如何在 wordpress 中使用 LIKE 搜索类别名称的帖子?

PHPWordPHPWord生成图表-柱形图 | 设置数值类别展示展示多组数据

PHPWordPHPWord生成图表-柱形图 | 设置数值类别展示展示多组数据