2

我在网上广泛查看并没有看到这个特定问题的答案(我认为)。

我解释自己的最佳方式是使用一些复制我的问题的代码。我做了一些临时数据:

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)

这就是 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 没有相同的行数。newdata1 具有 z=1 时的所有值,newdata3 具有 z=3 时的所有值。

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.012379  2.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 循环方法会导致比我希望的更多的问题。有什么建议可以完全避免这种情况并最终得到相同的结果吗?

请让我知道这是否令人困惑,或者我的代码是否只是草率!还在这个网站上格式化问题..

4

3 回答 3

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

或使用 base 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);)

于 2013-10-09T01:05:17.390 回答
2
> aggregate( . ~ z, data=temp, FUN=mean)
  z        x        y
1 1 1.505304 2.474642
2 3 1.533418 2.477191

当您将相同的功能应用于另一列类别中的多个列时,请考虑“聚合”。这是采用公式参数的版本,其中波浪号之前的“点”表示获取除“z”之外的所有列的平均值。

于 2013-10-09T01:18:25.027 回答
1

我想要做的是将函数应用于数据帧但应用于数据子集。

所以你可以使用subsetoraggregate函数:

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 

希望能帮助到你!

于 2013-10-09T01:29:54.053 回答