2012-07-31 51 views
6

在程序員閱讀R I看到這個功能一個基礎研發功能

oddcount <- function(x) { 
    k <- 0 
    for (n in x) { 
    if (n %% 2 == 1) k <- k+1 
    } 
    return(k) 
} 

我寧願把它寫在一個簡單的樣式(即口齒不清)

(defn odd-count [xs] 
    (count (filter odd? xs))) 

我看到的功能長度相當於計數,我可以寫奇數?那麼是否有內置的映射/過濾器/刪除類型功能?

回答

11

一個以上R的方式這樣做是爲了避免for迴路,並使用矢量:

oddcount <- function(x) { 
    sum(x %% 2) 
} 

x與2之間的比較輸出爲x本身是一個向量。總和計算矢量的總和,其中TRUE等於1且FALSE等於零。通過這種方式,函數計算向量中的奇數個數。

這已經導致更簡單的語法,儘管對於非矢量化人員,for循環往往更容易閱讀。我非常喜歡矢量化語法,因爲它更短。儘管如此,我寧願爲x使用更具描述性的名稱。 number_vector

+1

在這種情況下,它可能會更短,你不需要'== 1',因爲'%%'只會返回0和1。使用'sum(x %% 2)'。這可能會更快一些,因爲您不會生成邏輯並將其轉換回數字。有些人可能會發現更長的版本更具可讀性(如果您將其擴展到尋找的數字是或不是2以外的倍數,那麼您需要更長的版本。 – 2012-07-31 15:41:54

5

你應該看看funprog庫,其中包括mapfilterreduce

+0

感謝,長度(過濾器(odd_p,xs))似乎做了這項工作,似乎我是基於最後一個答案問錯了問題:) – ChrisR 2012-07-31 11:44:05

+0

使用'funprog'沒有什麼錯,但使用標準R你可以在代碼中獲得相同的簡短。 – 2012-07-31 11:46:21

+0

這是個好點子,@保羅。試圖強制使用一種範式(矢量化)的語言進入另一個範式(功能性)通常會導致不必要的冗長代碼。 – 2012-07-31 11:49:49

12

在R中,當您使用矢量時,人們通常喜歡一次處理整個矢量而不是循環遍歷它(請參閱this討論)。

從某種意義上說,R確實具有「內置」過濾器和減少功能:可以選擇矢量子集的方式。它們在R中非常方便,並且有幾種方法可以解決它 - 我會告訴你們一對夫婦,但是如果你閱讀R並在其他站點上查看其他人的代碼,那麼你將獲得更多的信息。我還會考慮看看?which?'[',它比我在這裏有更多的例子。

第一種方法是簡單地選擇你想要的元素。你可以使用這個,如果你知道你想要的元素的索引:

x <- letters[1:10] 
> x 
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" 

如果我們只希望前五個字母,我們可以這樣寫:

x[1:5] 
x[c(1,2,3,4,5)] # a more explicit version of the above 

您還可以選擇哪些元素通過使用減號不想要的,例如:

x[-(6:10)] 

另一種方式來選擇元素是通過使用布爾向量:

x <- 1:5 
selection <- c(FALSE, TRUE, FALSE, TRUE, FALSE) 
x[selection] # only the second and fourth elements will remain 

這一點很重要,因爲我們可以通過把一個向量比較函數創建一個這樣的載體:

selection <- (x > 3) 
> selection 
[1] FALSE FALSE FALSE TRUE TRUE 

x[selection] # select all elements of x greater than 3 
x[x > 3]  # a shorthand version of the above 

再次,我們可以選擇我們使用(注意,由於比較的相對這是布爾,我們使用!而不是-):

x[!(x > 3)] # select all elements less than or equal to 3 

如果你想要做的向量比較,你應該考慮%in%功能。例如:

x <- letters[1:10] 
> x %in% c("d", "p", "e", "f", "y") 
[1] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE 

# Select all elements of x that are also "d", "p", "e", "f", or "y" 
x[x %in% c("d", "p", "e", "f", "y")] 
# And to select everything not in that vector: 
x[!(x %in% c("d", "p", "e", "f", "y"))] 

以上只是一些例子;我肯定會推薦文檔。我知道在你已經接受了答案之後這是一個很長的帖子,但是這種事情是非常重要的,如果你是R的新手,那麼理解它會爲你節省很多時間和痛苦,所以我認爲我會分享幾種與你一起做的方法。

+0

謝謝,這絕對有幫助。 – ChrisR 2012-07-31 12:31:35