2012-11-21 182 views
1

我有一個由三列組成的數據幀(請參閱代碼示例)。第一列包含類別(a),第二列是觀測數量(b),第三列是這些觀測值的平均值(c)。R:在條件下替換數據幀中的值

#create a test df 
    a<-factor(c("aaa","aaa","aaa","ddd","eee","ddd","aaa","ddd")) 
    b<-c(3,4,1,3,5,7,3,2) 
    c<-c(1,2,NA,4,5,6,7,NA) 
    df.abc<-data.frame(a=a,b=b,c=c) 
    df.abc 

如果觀察的數目爲1或2,其中標記爲缺失值(NA)的條目。

因此,我的功能的目的是用每個類別的平均值替換這些缺失值。

我帶了我一段時間,但我得到了一個功能工作,用一個類別代替所有缺失值(如果觀察結果爲1)。它看起來像這樣:

#function to substitue the missing values in row c by their means 
    #according to their categories 
    function.abc<-function(x){ 
     ifelse(
      (df.abc[,1]==x)&(df.abc[,2]==1), 
      mean(df.abc$c[df.abc$a ==x],na.rm=TRUE), 
      df.abc[,3] 
     ) 
    } 

測試這一功能:

#test the function for the category "ccc" 
    function.abc("aaa") 

它工作的很好(但僅僅是平均值,而不是平均平均值)的輸出是:

[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000不適用

現在我的問題是,我有很多類別(n = 32),我試圖將這個函數應用於包含我的矢量類別。在這種情況下的simpe例子是:

#test the function for a testvector 
    test.vector<-c("aaa","ddd") 
    function.abc(test.vector) 

輸出爲:

[1] 1.0 2.0 4.5 4.0 5.0 6.0 7.0 NA

所以,很顯然,這將不起作用了...

任何人都可以幫我重新安排功能嗎?我很新的節目,它仍然是一個很大的挑戰,我設計短期和goodworking功能...

編輯:

我想輸出是: [1] 1.000000 2.000000 3.20000 4.000000 5.000000 6.000000 7.000000 5.000000

使得組aaa的平均(3.20000)代入AAA NA值和組DDD的平均值(5.0000000)代入NA在DDD ...

+0

目前尚不清楚你想要的最後一種情況下可能返回的。 –

+0

他會想'[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 5.00000'我相信。 –

+0

考慮到問題的陳述,我不認爲所提供的答案都是正確的。如果三個項目在值爲'= c(1,2,7)'的類別「aaa」中,計數爲「= c(3,4,3)',那麼加權平均值不是3.3333,而是3.2。如果我對問題陳述的理解是錯誤的,那麼也許可以修改這個問題來澄清爲什麼計數不能用於計算平均值? –

回答

1

爲了與多個列進行一個類別,你將需要使用的東西,分割數據幀,然後作用於組件內工作。 lapply(split(df, fac), function(x) {...})範例適用於此。或者您可以使用transformplyr包。

> lapply(split(df.abc, df.abc$a), 
       function(dfrm) { dfrm[is.na(dfrm$c), "c"] <- 
        weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"]) 
         dfrm}) 
       # need to evaluate dfrm in order to return the full value. 
$aaa 
    a b c 
1 aaa 3 1.0 
2 aaa 4 2.0 
3 aaa 1 3.2 
7 aaa 3 7.0 

$ddd 
    a b c 
4 ddd 3 4.0 
6 ddd 7 6.0 
8 ddd 2 5.4 

$eee 
    a b c 
5 eee 5 5 

然後,您可以rbind他們使用`do.call:

do.call(rbind, lapply(split(df.abc, df.abc$a), 
      function(dfrm) { dfrm[is.na(dfrm$c), "c"] <- 
       weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"]) 
        dfrm})) 
     a b c 
aaa.1 aaa 3 1.0 
aaa.2 aaa 4 2.0 
aaa.3 aaa 1 3.2 
aaa.7 aaa 3 7.0 
ddd.4 ddd 3 4.0 
ddd.6 ddd 7 6.0 
ddd.8 ddd 2 5.4 
eee eee 5 5.0 
+0

爲我工作。甚至沒有考慮先拆分它,但這是完全合理的。謝謝! – Joschi

0

I」米不太清楚你的意思,但如果你的意思是包括所有這樣的行,你可以在%中使用%。

function.abc<-function(x){ 
    ifelse(
    (df.abc[,1] %in% x)&(df.abc[,2]==1), 
    mean(df.abc$c[df.abc$a %in% x],na.rm=TRUE), 
    df.abc[,3] 
) 
} 

> function.abc("aaa") 
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000  NA 

> test.vector<-c("aaa","ddd") 
> function.abc(test.vector) 
[1] 1 2 4 4 5 6 7 NA 

的最後一個元素是NA因爲列「B」不是1

0

CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T))將讓你指按類別。

 aaa  ddd  eee 
3.333333 5.000000 5.000000 

這樣做的所有所有的人:

> CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T)) 
> ifelse(is.na(df.abc$c), CatMeans[df.abc$a], df.abc$c) 
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 5.000000 

你可以說,到功能我敢肯定。如果你只是想"aaa""ddd",那麼你可以有ifelse(is.na(df.abc$c) & df.abc$a %in% c("aaa","ddd"),...