2017-04-14 4 views
1

与えられた単語の文字の頻度を示す2つの引数を持つ関数を作成したいとします。x < - 単語、y < - 文字。だから、私は次の関数を作成:文字列の文字頻度

frequency <- function(x,y) 
{ 
    word <- strsplit(x,"") 
    counter <- 0 
    for (i in 1:length(word)){ 
     if (word[i] == y) counter=counter+1 
    } 
    print(counter) 
} 

この機能の基本的な考え方は、与えられた単語の文字を分割することでした、それらを反復し、条件が満たされた場合、カウンタの値を増やします。しかし、この関数は常に0の値を返します。これは何の原因ですか?

+0

ループの代わりに、 'sum(word == y)'を試してください。しかし、あなたが見ている問題は 'strsplit(x、" ")[[1]]'を実行するか、 'unlist'をラップする必要があるからです。 – Frank

+0

[[1]]]を追加する必要がある理由を説明できますか? –

+0

最後に値を返す必要があります。 'print'は値を画面に出力しますが、NULLオブジェクトを返します。 'print(counter)'を 'counter'や' return(counter) 'に置き換えてください。 – lmo

答えて

1

フランクの指摘したように、通常はループを避ける方が良いです。あなたは簡単にそうようにそれを行うことができます:forループを使用せずにこれを行うには

word <-"Word" 
y <-"d" 

sum(unlist(strsplit(word,""))==y) 
[1] 1 
0

もう一つの方法は、周波数の名前のベクトルを返すtable機能を、使用することです。また、リストを返すので、strsplitを使用した後でアンリストする必要があります。最後に、私は、文字列(例えば、「バナナ」は「バナナ」に変換されます)大文字で使用されているだけの場合には機能tolower

freq <- function(x,y) { 
    word <- tolower(unlist(strsplit(x,""))) 
    word_table <- table(word) 
    ans <- word_table[names(word_table)==y] 
    return(ans) 
} 

freq("mississippi", "s") 

戻り、このよう

s 
4 

注意を使用しました単一の単語が供給された場合にのみ機能し、代わりに単語の文字列がxに追加された場合、各単語の頻度を個別に返すように関数を一般化する必要があります。

0

これはstrsplit()で行う必要があるかどうかわかりません。そうでない場合:

x <- "c" 
y <- "confluence is crazy cc" 
count_string <- function(x,y){ 
    count <- if(unlist(gregexpr(x,y))[1] == -1) 0 else length(unlist(gregexpr(x,y))) 
    return(count) 
    } 
> count_string(x,y) 
[1] 5 
> count_string("xx",y) 
[1] 0 

gregexpr()は、リスト内で見つかった各一致の位置を返します。一致するものが見つからない場合は-1を返します。あなたの文字列で一致した回数を返すためにリストを数えます。

+0

これは、 'count_string(" foo "、" b ")' –

+0

Ackのように、一致するものがないときに間違った答えを返します。ありがとう@MartinMorgan私はそれを修正する方法を見てみましょう。 – akaDrHouse

0

ロジックはすべて正しく見えます。だから何かがあなたが思っていることをしていない。

コンソールでword[i]をチェックしてください。それはリストです。最初の要素は型、2番目の値を記述します。だから、配列を文字と比較しています。

Browse[2]> word <- strsplit("something",'') 
Browse[2]> word[0] 
list() 
Browse[2]> word[1] 
[[1]] 
[1] "s" "o" "m" "e" "t" "h" "i" "n" "g" 

R(Matlab、その他のデータ言語)では、ループを使用することをお勧めします。むしろ、R関数を使ってリストを調べるべきです。その後

Browse[2]> frequency("hih","h") 
2 
2

別のバージョンがraw()ベクターにあなたの「言葉」を翻訳することです

frequency <- function(x,y) 
{ 
    word <- strsplit(x,'') 
    val <- table(word[1] == y)["TRUE"] 
    cat(val) 
} 
frequency("hih","h") 

と:それはあなたが関数に比較を送信する機能的なアプローチを使用しています - 機能tableをチェック文字 'raw()ベクトルと比較してください。ここで

frequency = function(word, letter) 
    sum(charToRaw(word) == charToRaw(letter)) 

四つの異なるソリューションが

f0 <- function(word, letter) 
    sum(strsplit(word, "")[[1]] == letter) 

f1 <- function(word, letter) 
    sum(charToRaw(word) == charToRaw(letter)) 

f2a <- function(word, letter) 
    length(unlist(gregexpr(letter, word))) 

f2b <- function(word, letter) 
    length(unlist(gregexpr(letter, word, fixed=TRUE))) 

いくつかの正当性と性能を比較して

> word <- "foo" 
> letter <- "o" 
> identical(f0(word, letter), f1(word, letter)) 
[1] TRUE 
> identical(f0(word, letter), f2a(word, letter)) 
[1] TRUE 
> identical(f0(word, letter), f2b(word, letter)) 
[1] TRUE 
> letter <- "a" 
> identical(f0(word, letter), f1(word, letter)) 
[1] TRUE 
> identical(f0(word, letter), f2a(word, letter)) 
[1] FALSE 
> identical(f0(word, letter), f2b(word, letter)) 
[1] FALSE 
> word <- paste(sample(letters, 10000, TRUE), collapse="") 
> letter <- "a" 
> microbenchmark(
+  f0(word, letter), f1(word, letter), 
+  f2a(word, letter), f2b(word, letter) 
+) 
Unit: microseconds 
       expr  min  lq  mean median  uq  max neval 
    f0(word, letter) 558.433 562.4755 579.03451 583.5590 584.8920 628.946 100 
    f1(word, letter) 71.482 78.7100 100.85787 80.0275 81.7035 2195.366 100 
f2a(word, letter) 277.618 278.7280 280.94280 279.4870 280.4270 302.683 100 
f2b(word, letter) 66.888 68.1800 69.07205 68.6205 69.3100 84.300 100 

f2b()は最速のも正しくないです。 f1()は現時点では高速です(速度は手元の作業では重要ではありませんが)が正しいと思われます。

0
mf <- function(x, y){ 
    count <- table(strsplit(x, '')[[1]]) 
    count[names(count) == y] 
} 

mf('hello world', 'l') 
# l 
# 3