2012-01-07 56 views
3

我是R新手,無法弄清楚在下面的代碼中我可能會做錯什麼,以及如何加速它。 我有一個數據集,並希望添加一個包含從兩列數據計算的平均值的列。請看看下面的代碼(警告:它可能需要一些時間來閱讀我的問題,但代碼運行罰款R):使用R中的一些hashmap方法高效地更新數據框列

讓我先定義一個數據集DF(我再次爲長說明道歉

> df<-data.frame(prediction=sample(c(0,1),10,TRUE),subject=sample(c("car","dog","man","tree","book"),10,TRUE)) 
> df 
    prediction subject 
1   0  man 
2   1  dog 
3   0  man 
4   1 tree 
5   1  car 
6   1 tree 
7   1  dog 
8   0 tree 
9   1 tree 
10   1 tree 

接下來的代碼)我添加一個新列稱爲subjectRate從新的表定義我生成rateMap以便部門自動化df,可以

df$subjectRate <- with(df,ave(prediction,subject)) 
> df 
     prediction subject subjectRate 
    1   0  man   0.0 
    2   1  dog   1.0 
    3   0  man   0.0 
    4   1 tree   0.8 
    5   1  car   1.0 
    6   1 tree   0.8 
    7   1  dog   1.0 
    8   0 tree   0.8 
    9   1 tree   0.8 
    10   1 tree   0.8 

在先前獲得的平均值初始化的subjectRate列中填入新數據。

rateMap <- df[!duplicated(df[, c("subjectRate")]), c("subject","subjectRate")] 
> rateMap 
    subject subjectRate 
1  man   0.0 
2  dog   1.0 
4 tree   0.8 

現在我定義一個新的數據集與老主題的東風,新科

> dfNew<-data.frame(prediction=sample(c(0,1),15,TRUE),subject=sample(c("car","dog","man","cat","book","computer"),15,TRUE)) 
> dfNew 
    prediction subject 
1   1  man 
2   0  cat 
3   1 computer 
4   0  dog 
5   0  book 
6   1  cat 
7   1  car 
8   0  book 
9   0 computer 
10   1  dog 
11   0  cat 
12   0  book 
13   1  dog 
14   1  man 
15   1  dog 

我的問題的組合:如何有效地創建第三列?目前我正在運行下面的測試,在地圖中查找主題速率,如果找到則輸入值,如果沒有,則輸入0.5。

> all_facts<-levels(factor(rateMap$subject)) 
> dfNew$subjectRate <- sapply(dfNew$subject,function(t) ifelse(t %in% all_facts,rateMap[as.character(rateMap$subject) == as.character(t),][1,"subjectRate"],0.5)) 
> dfNew 
    prediction subject subjectRate 
1   1  man   0.0 
2   0  cat   0.5 
3   1 computer   0.5 
4   0  dog   1.0 
5   0  book   0.5 
6   1  cat   0.5 
7   1  car   0.5 
8   0  book   0.5 
9   0 computer   0.5 
10   1  dog   1.0 
11   0  cat   0.5 
12   0  book   0.5 
13   1  dog   1.0 
14   1  man   0.0 
15   1  dog   1.0 

,但與真正的數據集(20多萬行)用類似計算平均多列,代碼需要很長的時間來運行。有人可能會建議一個更好的方法來做我想要達到的目標嗎?也許有些合併或者某種東西,但我沒有想法。 謝謝。

回答

6

我懷疑(但我不知道,因爲我沒有測試過),這將是更快:

dfNew$subjectRate <- rateMap$subjectRate[match(dfNew$subject,rateMap$subject)] 

,因爲它大多隻是使用索引和match。我想,這當然更簡單一些。這將在「新」的價值觀填補NA S,而不是0.5,然後可以在不過你喜歡充滿,

dfNew$subjectRate[is.na(dfNew$subjectRate)] <- newValue 

如果ave一塊是特別慢,標準的建議是這些天來使用data.table包:

require(data.table) 
dft <- as.data.table(df) 
setkeyv(dft, "subject") 
dft[, subjectRate := mean(prediction), by = subject] 

,這可能會吸引一些意見建議的方式來勉強維持多一點的速度進行數據彙總表中的最後一行。事實上,合併或加入使用純粹的data.tables可能會更加輕鬆(也很快),所以您可能也想調查該選項。 (請參閱?data.table最下方的一堆示例。)

+0

非常感謝。到目前爲止,我只使用了您發佈的前兩個代碼片段,而現在它只需要不到一秒的時間來處理所有內容。我一定會看看data.table。 – ak3nat0n 2012-01-07 08:39:56

+1

嗨。我當時錯過了這一個。當':='按組實現時,最後一行會更快更優雅:'dft [,subjectRate:= mean(prediction),by = subject]'。 – 2012-02-03 17:59:13

相關問題