当类别名称与数据混合时如何提取组类别
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
【讨论】:
太棒了,非常感谢您的详细解释以上是关于当类别名称与数据混合时如何提取组类别的主要内容,如果未能解决你的问题,请参考以下文章
如何在 wordpress 中使用 LIKE 搜索类别名称的帖子?