2017-04-14 86 views
1

我想創建一個帶有兩個參數的函數,這兩個參數將顯示給定字中字符的頻率: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對象。用'counter'或'return(counter)'替換'print(counter)'。 – lmo

回答

1

正如弗蘭克指出的那樣,通常避免循環會更好。你可以做到這一點很容易,像這樣:

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

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

另一種方式來做到這一點,而無需使用for循環將使用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]。這是一個列表。第一個元素描述類型,第二個值。所以你將一個數組與一個字母進行比較。

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函數來查看列表。退房的功能table - 它使用在你發送的比較功能的功能的方法:

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

然後

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

另一個版本是你的「字」翻譯成raw()載體與'字母'作爲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()是最快的,但也是不正確;目前看起來似乎很快(儘管速度對於手頭的任務來說可能並不重要)並且是正確的。

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

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