2013-10-09 52 views
1

我在網上廣泛查找並沒有看到這個特定問題的答案(我認爲)。R將函數應用於數據框的子集

我自我解釋的最佳方式是使用一些複製我的問題的代碼。 我做了一些臨時數據:

x <- runif(100,1,2) 
y <- runif(100,2,3) 

z <- c(rep(1,100)) 
temp <- cbind(x,y,z) 

temp[1:25,3] = temp[1:25,3] +2 

temp <- as.data.frame(temp) 

而這就是臨時的樣子

  x  y z 
1 1.512620 2.552271 3 
2 1.133614 2.455296 3 
3 1.543242 2.490120 3 
4 1.047618 2.069474 3 
.  .  .  . 
.  .  .  . 
27 1.859012 2.687665 1 
28 1.231450 2.196395 1 

,並繼續直到數據幀(100行)結束。

我想要做的是將一個函數應用於數據框但是數據的子集。因此,例如,我想將函數均值應用於z = 3時的列x和y,並將函數均值應用於z = 1時的列x和y。所以我最終會得到4個值:當z = 1和z = 3時的x的均值,以及當z = 1和z = 3時的y的均值。對於我的實際數據集,當z =某個值的行數變化很大。

我一直在使用下面的代碼工作;然而,這讓我感到非常不安,因爲我覺得代碼可以更高效,並且理想地避免了for循環。

x <- c(unique(temp$z)) 

我使用^^來獲得唯一的z值(在這種情況下,z = 3和z = 1)。

for(i in x){ 
    assign(paste("newdata",i,sep=""),subset(temp[which(temp$z==i),],select=c("x","y"))) 
} 

所以我現在有兩個新的數據幀newdata1和newdata3沒有相同的行數。當z = 1時,newdata1具有所有值,而當z = 3時,newdata3具有所有值。

library(gdata) 

blah <-cbindX(newdata1,newdata3) 

我使用cbindX再次將子集數據組合到一個大數據框中。我不確定我爲什麼要這麼做(我很久以前就做過這個代碼)。我只記得這是我使用上面的for循環的唯一方法。代碼的主要問題是當我有多個z值時,手動輸入列表變得非常麻煩。如果Z從1到50不等,然後用戶將鍵入newdata1,newdata2,newdata3 ....等

但是......它的工作:

summ.test <- apply(blah,2,function(x) { 
c(min(x,na.rm=TRUE),median(x,na.rm=TRUE),max(x,na.rm=TRUE),sum(!is.na(x)))}) 

     x   y   x   y 
[1,] 1.028332 2.018162 1..009595 
[2,] 1.509049 2.504000 1.427981 2.455296 
[3,] 1.992704 2.998483 1.978359 2.970695 
[4,] 75.000000 75.000000 25.000000 25.000000 

所以我做了有效的創建是一個新的數據框,其中我從之前進行了子集化,並將感興趣的功能應用於它們。所以第一行是:z = 1時x的均值,z = 1時y的均值,z = 3時x的均值,z = 3時y的均值。

主要問題應該是相當明顯的:for循環方法子集的數據框會導致更多的問題,我希望。任何建議,以完全避免,並仍然以相同的結果?

請讓我知道這是否令人困惑,或者如果我的代碼只是簡單的馬虎!仍然在這個網站上格式化問題也..

回答

2
> aggregate(. ~ z, data=temp, FUN=mean) 
    z  x  y 
1 1 1.505304 2.474642 
2 3 1.533418 2.477191 

當將應用相同的函數的多個另一列的類別中的列考慮「聚合」。這是版本taht需要一個公式參數,其中代字號之前的「點」表示除了「z」之外的所有列的平均值。

+0

非常好。謝謝。總體看來對數據集的效果最好,特別是因爲我知道我以後會做更多更廣泛的功能。這似乎工作'聚合(x〜z,數據=溫度,FUN =函數(x)c(mn = min(x,na.rm = TRUE),sum(!is.na(x))))'for多種功能。理想情況下,我想對一堆不同數量的子集值進行迴歸,所以我會看看是否可以定製集合。謝謝。 –

3
library(data.table) 
DT <- as.data.table(temp) 
DT[, lapply(.SD, mean), by=z] 
    z  x  y 
1: 3 1.515801 2.309161 
2: 1 1.509637 2.532575 

或者用鹼R

with(temp, cbind(x=tapply(x, z, mean), y=tapply(y, z, mean))) 
     x  y 
1 1.509637 2.532575 
3 1.515801 2.309161 

PS,不要忘記設置一個種子,set.seed(1)用於示例;)

+0

這也很好。感謝您的回答和提示! –

1

我想要做的是將一個函數應用於數據框但是數據的子集。

所以,你可以使用subsetaggregate功能:

data = data.frame(x = runif(100), y = runif(100), z = sample(1:10, 100, replace = TRUE)) 

# get z > 3 AND z < 6 subset, for example 
new.data = subset(data, z > 3 & z < 6) ## CAUTION: use &, not && 

# use newdata 
cm = colMeans(new.data) 
print(cm) 

#  x   y   z 
# 0.4674450 0.5293915 4.5769231 

希望它能幫助!

相關問題