Допустим, у нас есть таблица продуктов питания:
product_id <- c(1, 1, 2, 2, 3, 3)
name <- c("Cheddar", "Cheddar", "Apple", "Apple", "Pizza", "Pizza")
category <- c("Dairy", "Cheese", "Food", "Fruit", "Food", NA)
products <- data.frame(product_id, name, category)

With categories set up in an irregular hierarchy:
level_1

My eventual goal is to delete duplicate products, keeping the lowest hierarchy level (i.e. more detail).

I don't necessarily need to keep the row with the most detail, just the label. So we could also just apply the most detailed category name to all rows in the group, and I can choose the row to remove later. But keep in mind there could be errors: we might have a row of Pizza = Fruit
and Pizza = Pizza
, which should just be ignored (that would need a manual fix).
Edit: The answers so far have been great, thank you for the help. There's just one thing missing from them:
In my real-world data I have errors in category, so I'm ignoring duplicates that are in different sections of the hierarchy tree. Imagine there's another section of this hierarchy for clothing > pants > jeans
. Then if I had these product duplicates:
+---------+----------+
| Product | Category |
+---------+----------+
| Apple | Food |
+---------+----------+
| Apple | Jeans |
+---------+----------+
I wouldn't want to keep "Jeans", even though it's a more specific category.
The only solution I can think of is this (and I don't know how to implement it in R):
- Put every level of hierarchy on the products table, and populate based on category
- Group by product
- Check that all rows in group match at level_1
- If yes, check level_2, if yes check level_3
- At each stage, if the mismatch is due to an NA, we have a winner and apply the existing category at that level
- If the mismatch is due to different categories, leave it
Alternatively, a solution could be a new column for the "highest-level common category", if that's an easier way to think about it.
Edit #2 - New datasets
product_id

level_1

Goal:

OR
введите описание изображения здесь