2012-01-09 107 views

回答

17

這個怎麼樣的基礎R解決方案:

df <- data.frame(group = rep(c("G1", "G2"), each = 10), 
       var1 = rnorm(20), 
       var2 = rnorm(20)) 

r <- by(df, df$group, FUN = function(X) cor(X$var1, X$var2, method = "spearman")) 
# df$group: G1 
# [1] 0.4060606 
# ------------------------------------------------------------ 
# df$group: G2 
# [1] 0.1272727 

然後,如果你想在一個data.frame形式的結果:

data.frame(group = dimnames(r)[[1]], corr = as.vector(r)) 
# group  corr 
# 1 G1 0.4060606 
# 2 G2 0.1272727 

編輯:如果你更喜歡基於plyr的解決方案,這裏是一個:

library(plyr) 
ddply(df, .(group), summarise, "corr" = cor(var1, var2, method = "spearman")) 
+0

謝謝Josh的及時回覆。他們都工作! ;-) – user1009166 2012-01-09 18:31:49

+0

(+1)很好的答案。那麼'r < - by(df,df $ group,FUN = function(X)cor(df [, - 1],method =「spearman」))'? – MYaseen208 2012-01-09 19:45:37

+0

@ MYaseen208。謝謝。您提供的代碼返回的內容稍有不同。我不知道它的名字,但它像方差 - 協方差矩陣,除了在每個單元格中有相關性。我使用的代碼會返回每個組的單個標量關聯。 – 2012-01-09 20:35:57

5

這裏是另一種方式來做到這一點:

# split the data by group then apply spearman correlation 
# to each element of that list 
j <- lapply(split(df, df$group), function(x){cor(x[,2], x[,3], method = "spearman")}) 

# Bring it together 
data.frame(group = names(j), corr = unlist(j), row.names = NULL) 

相比我的方法,Josh的方法,以及使用rbenchmark的plyr解決方案:

Dason <- function(){ 
    # split the data by group then apply spearman correlation 
    # to each element of that list 
    j <- lapply(split(df, df$group), function(x){cor(x[,2], x[,3], method = "spearman")}) 

    # Bring it together 
    data.frame(group = names(j), corr = unlist(j), row.names = NULL) 
} 

Josh <- function(){ 
    r <- by(df, df$group, FUN = function(X) cor(X$var1, X$var2, method = "spearman")) 
    data.frame(group = attributes(r)$dimnames[[1]], corr = as.vector(r)) 
} 

plyr <- function(){ 
    ddply(df, .(group), summarise, "corr" = cor(var1, var2, method = "spearman")) 
} 


library(rbenchmark) 
benchmark(Dason(), Josh(), plyr()) 

這給輸出

> benchmark(Dason(), Josh(), plyr()) 
    test replications elapsed relative user.self sys.self user.child sys.child 
1 Dason()   100 0.19 1.000000  0.19  0   NA  NA 
2 Josh()   100 0.24 1.263158  0.22  0   NA  NA 
3 plyr()   100 0.51 2.684211  0.52  0   NA  NA 

所以看來我的方法稍微快一點,但不是太多。我認爲喬希的方法更直觀一些。 plyr解決方案是最容易編碼的,但它不是最快的(但它確實更方便)!

+0

感謝您考慮用'基準測試'來測試這些。 +1將它們放在一起。我有幾個額外的評論。 (1)通過反覆調用基準測試,'lapply(split)(...)和'by(...)'方法之間的差異更像是7-10%。(2)如果您有興趣在追求這一點的時候,在一些大型數據框架上測試三種方法可能會更有用,包括1000+組和1e6 +行。乾杯! – 2012-01-09 17:48:07

+0

非常感謝Dason! – user1009166 2012-01-09 18:32:45

3

如果您想爲大量組提供高效的解決方案,那麼data.table即可。

library(data.table) 
DT <- as.data.table(df) 
setkey(DT, group) 
DT[,list(corr = cor(var1,var2,method = 'spearman')), by = group] 
+0

+1注意'setkey '是可選的,對於非常大的數據集(例如1e7行+),鍵控的速度比非鍵控的速度快,其中有很多大的組,非鍵控已經非常快。 – 2012-09-19 08:54:54