2017-11-10 21 views
3

サブストリングを共有する長いリストの文字列があります。このリストはイベントストリームのデータから来ているので、何万行もありますが、この例では単純化します。ペット:サブストリングキーを持つ検索文字列R

+--------------------------------+ 
|    Pets    | 
+--------------------------------+ 
| "one calico cat that's smart" | 
| "German Shepard dog"   | 
| "A Chameleon that is a Lizard" | 
| "a cute tabby cat"    | 
| "the fish guppy"    | 
| "Lizard Gecko"     | 
| "German Shepard dog"   | 
| "Budgie Bird"     | 
| "Canary Bird in a coal mine" | 
| "a chihuahua dog"    | 
+--------------------------------+ 
dput output: structure(list(Pets = structure(c(8L, 6L, 1L, 3L, 9L, 7L, 6L, 4L, 5L, 2L),.Label = c("A Chameleon that is a Lizard", "a chihuahua dog", "a cute tabby cat", "Budgie Bird", "Canary Bird in a coal mine", "German Shepard dog", "Lizard Gecko", "one calico cat that's smart", "the fish guppy"), class = "factor")), .Names = "Pets", row.names = c(NA, -10L), class = "data.frame") 

私はペットのジェネリックタイプ(など、犬、猫、)に基づいて情報を追加したいと私は、この情報を保持しているキーテーブルを持っている:

+----------+----------------+ 
| key | classification | 
+----------+----------------+ 
| "dog" | "canine"  | 
| "cat" | "feline"  | 
| "lizard" | "reptile"  | 
| "bird" | "avian"  | 
| "fish" | "fish"   | 
+----------+----------------+ 
dput output: structure(list(key = structure(c(3L, 2L, 5L, 1L, 4L), .Label = c("bird", "cat", "dog", "fish", "lizard"), class = "factor"), classification = structure(c(2L, 3L, 5L, 1L, 4L), .Label = c("avian", "canine", "feline", "fish", "reptile"), class = "factor")), .Names = c("key", "classification"), row.names = c(NA, -5L), class = "data.frame") 

どうかPetsテーブルの「長い文字列」を使用して、キーテーブルに関連するclassificationを見つけますか?問題は、私のルックアップ文字列がキーテーブルにある部分文字列を含んでいることです。

私はこのようなgreplを使用して開始しています:

key[grepl(pets[1,1], key[ , 2]), ] 

「猫」ですが、「三毛猫」は、キーリストにないので、しかし、これは動作しません。探している結果は「feline」です。

(注:私自身のコードでは、これは適用関数内にあり、データの各行をループするため、単純に切り替えることはできません。pets[1,1]の代わりにpets[n,1]です。その結果をイベントストリームデータに追加して解析します)。

これを行う方法について私は頭を悩ましています。何かアドバイス?

+0

これは、と思われますキーは常に各 "長い文字列"の2番目の単語です。これは合理的な仮定ですか? – useR

+0

残念ながら、いいえ。弦には数か所から数多くの言葉があります。私はちょうどそこに 'キーの言葉があることを知っている。 – JoeM05

+1

次に、この仮定に合わない長い文字列を含むサンプルを提供する必要があります。また、 'dput(my_data)'の出力をコピーしてあなたの質問に貼り付けてください。 – useR

答えて

2

パッケージfuzzyjoinを使用すると、これらの作業を非常に簡単に行うことができます。

ここでは、その試合であることrwosのための基準はstringr::str_detect

library(tibble) 
library(fuzzyjoin) 

pets <- tribble(
          ~pets, 
    "one calico cat that\'s smart", 
      "German Shepard dog", 
    "A Chameleon that is a Lizard", 
       "a cute tabby cat", 
       "the fish guppy", 
        "Lizard Gecko", 
      "German Shepard dog", 
        "Budgie Bird", 
    "Canary Bird in a coal mine", 
       "a chihuahua dog" 
) 

key <- tribble(
     ~key, ~classification, 
     "dog",  "canine", 
     "cat",  "feline", 
    "lizard",  "reptile", 
    "bird",   "avian", 
    "fish",   "fish" 
) 

regex_left_join(pets, key, by = c("pets" = "key"), ignore_case = TRUE) 

#> # A tibble: 10 x 3 
#>       pets key classification 
#>       <chr> <chr>   <chr> 
#> 1 one calico cat that's smart cat   feline 
#> 2   German Shepard dog dog   canine 
#> 3 A Chameleon that is a Lizard lizard  reptile 
#> 4    a cute tabby cat cat   feline 
#> 5    the fish guppy fish   fish 
#> 6     Lizard Gecko lizard  reptile 
#> 7   German Shepard dog dog   canine 
#> 8     Budgie Bird bird   avian 
#> 9 Canary Bird in a coal mine bird   avian 
#> 10    a chihuahua dog dog   canine 
+0

これは機能しました。便利な図書館、ありがとうaustensen – JoeM05

1

のような正規表現マッチングによって決定されることを除いて、普通の左のように参加する働きregex_left_join、(例えばdplyr::left_join)を使用することができますあなたは、各ペットのためのキーのリストを作成して、テーブルでそれらを見ることができます

Pattern = paste(KeyTable$key, collapse="|") 
Pattern = paste0(".*(", Pattern, ").*") 
Type = tolower(sub(Pattern, "\\1", ignore.case=TRUE, Pets)) 
KeyTable$classification[match(Type, KeyTable$key)] 
[1] "feline" "canine" "reptile" "feline" "feline" "canine" "fish" 
[8] "reptile" "canine" "avian" "avian" "canine" 

データ

ここで
KeyTable = read.table(text="key classification 
dog canine 
cat feline 
lizard reptile 
bird avian  
fish fish", 
header=TRUE, stringsAsFactors=FALSE) 

Pets = c("calico cat", 
"Shepard dog" , 
"Chameleon Lizard", 
"calico cat", 
"tabby cat", 
"chihuahua dog", 
"guppy fish", 
"Gecko Lizard", 
"Shepard dog", 
"Budgie Bird", 
"Canary Bird" , 
"chihuahua dog") 
1

hashmapを使用して別の方法です:

library(hashmap) 

hash_table = hashmap(Lookup$key, Lookup$classification) 

Pets %>% 
    separate_rows(Pets, sep = " ") %>% 
    mutate(class = hash_table[[tolower(Pets)]]) %>% 
    na.omit() %>% 
    select(Key = Pets, class) %>% 
    bind_cols(Pets, .) 

結果:

> hash_table 
## (character) => (character) 
##  [fish] => [fish]  
##  [bird] => [avian]  
## [lizard] => [reptile] 
##  [cat] => [feline] 
##  [dog] => [canine] 

          Pets Key class 
1 one calico cat that's smart cat feline 
2   German Shepard dog dog canine 
3 A Chameleon that is a Lizard Lizard reptile 
4    a cute tabby cat cat feline 
5    the fish guppy fish fish 
6     Lizard Gecko Lizard reptile 
7   German Shepard dog dog canine 
8     Budgie Bird Bird avian 
9 Canary Bird in a coal mine Bird avian 
10    a chihuahua dog dog canine 

データ:

Pets = structure(list(Pets = c("one calico cat that's smart", "German Shepard dog", 
           "A Chameleon that is a Lizard", "a cute tabby cat", "the fish guppy", 
           "Lizard Gecko", "German Shepard dog", "Budgie Bird", "Canary Bird in a coal mine", 
           "a chihuahua dog")), .Names = "Pets", row.names = c(NA, -10L), class = "data.frame") 


Lookup = structure(list(key = c("dog", "cat", "lizard", "bird", "fish"), 
         classification = c("canine", "feline", "reptile", "avian", 
         "fish")), class = "data.frame", .Names = c("key", "classification" 
        ), row.names = c(NA, -5L))