ある列にカテゴリラベルがあり、別の列に一致する用語/パターンがある別のデータフレームに基づいて分類する必要がある文字列の列を持つデータフレームがあります。
50 以上のカテゴリがあり、各文字列は複数のカテゴリに一致する可能性がありますが、他のカテゴリには一致しません。これらの文字列にカテゴリ ラベルを効率的にタグ付けするにはどうすればよいですか?
以下は、簡単なサンプル データセットと、取得したい出力です。違いがあるとすれば、実際のデータ セット内の文字列はこれらのサンプル文字列よりもはるかに長く、その数は数十万になります。
recipes <- c('fresh asparagus', 'a bunch of bananas', 'one pound pork', 'no fruits, no veggies, no nothing', 'broccoli or spinach','I like apples, asparagus, and pork', 'meats like lamb', 'venison sausage and fried eggs', 'spinach and arugula salad', 'scrambled or poached eggs', 'sourdough english muffins')
recipes_df <- data.frame(recipes, stringsAsFactors = FALSE)
category <- c('vegetable', 'fruit', 'meat','bread','dairy')
items <- c('arugula|asparagus|broccoli|peas|spinach', 'apples|bananas|blueberries|oranges', 'lamb|pork|turkey|venison', 'sourdough', 'buttermilk|butter|cream|eggs')
category_df <- data.frame(category, items)
これは私が得たいと思っている出力です:
recipes recipes_category
1 fresh asparagus vegetable
2 a bunch of bananas fruit
3 one pound pork meat
4 no fruits, no veggies, no nothing <NA>
5 broccoli or spinach vegetable
6 I like apples, asparagus, and pork fruit, vegetable, meat
7 meats like lamb meat
8 venison sausage and fried eggs meat, dairy
9 spinach and arugula salad vegetable
10 scrambled or poached eggs dairy
11 sourdough english muffins breads
grepl と for ループまたは apply のバージョンの組み合わせが必要だと思いますが、以下で試した例では、R をほとんど理解していないことがよくわかります。たとえば、sapply を使用すると期待どおりの結果が得られますが、よくわかりsapply(category_df$items, grepl, recipes_df$recipes)
ませんこれらの結果を必要な単純な列に変換する方法。
ここにある categorize 関数を使用すると、各文字列に対して 1 つのカテゴリのみが一致します。
categorize_food <- function(df, searchString, category) {
df$category <- "OTHER"
for(i in seq_along(searchString)) {
list <- grep(searchString[i], df[,1], ignore.case=TRUE)
if (length(list) > 0) {
df$category[list] <- category[i]
}
}
df
}
recipes_cat <- categorize_food(recipes_df, category_df$items, category_df$category)
同様に、ここで見つかった関数は私が探しているものに最も近いものですが、カテゴリ番号がそのようにマッピングされる理由がわかりません. 野菜のカテゴリは 2 ではなく 1、乳製品は 3 ではなく 5 になると思います。
vec = category_df$items
recipes_df$category = apply(recipes_df, 1, function(u){
bool = sapply(vec, function(x) grepl(x, u[['recipes']]))
if(any(bool)) vec[bool] else NA
})