在两个数组之间划分特定值

时间:2011-09-15 14:52:10

标签: r plyr

我是一名初级R用户,尝试使用40,000行和300列的数据集。我找到了一个我想做的解决方案,但是我的机器需要一个多小时来运行我的代码,我觉得专家可以帮助我提供更快的解决方案(因为我可以在一半的时间内在excel中做到这一点) 。我会在最后发布我的解决方案。

我想做的是以下内容:

  1. 根据YYYYMMbucket列的值计算每列NY1到NYn的平均值。

  2. 将原始值除以其平均YYYYMMbucket值。

  3. 以下是我原始数据集的示例:

         YYYYMMbucket    NY1  NY2  NY3   NY4
    1      200701.3     0.309  NA 20.719 16260
    2      200701.3     0.265  NA 19.482 15138
    3      200701.3     0.239  NA 19.168 14418
    4      200701.3     0.225  NA 19.106 14046
    5      200701.3     0.223  NA 19.211 14040
    6      200701.3     0.234  NA 19.621 14718
    7      200701.3     0.270  NA 20.522 15780
    8      200701.3     0.298  NA 22.284 16662
    9      200701.2     0.330  NA 23.420 16914
    10     200701.2     0.354  NA 23.805 17310
    11     200701.2     0.388  NA 24.095 17448
    12     200701.2     0.367  NA 23.954 17640
    13     200701.2     0.355  NA 23.255 17748
    14     200701.2     0.346  NA 22.731 17544
    15     200701.2     0.347  NA 22.445 17472
    16     200701.2     0.366  NA 21.945 17634
    17     200701.2     0.408  NA 22.683 18876
    18     200701.2     0.478  NA 23.189 21498
    19     200701.2     0.550  NA 23.785 22284
    20     200701.2     0.601  NA 24.515 22368
    

    这就是我的平均值:

         YYYYMMbucket  NY1M     NY2M
    1      200701.1  0.4424574   NA
    2      200701.2  0.4530000   NA
    3      200701.3  0.2936935   NA
    4      200702.1  0.4624063   NA
    5      200702.2  0.4785937   NA
    6      200702.3  0.3091161   NA
    7      200703.1  0.4159687   NA
    8      200703.2  0.4491875   NA
    9      200703.3  0.2840081   NA
    10     200704.1  0.4279137   NA
    

    我希望我的最终输出看起来如何:

      NY1avgs   NY2avgs    NY3avgs
    1  1.052117     NA  0.7560868
    2  0.9023011    NA  0.7109456
    3  0.8137734    NA  0.699487
    4  0.7661047    NA  0.6972245
    5  0.7592949    NA  0.7010562
    6  0.7967489    NA  0.7160181
    7  0.9193256    NA  0.7488978
    8  1.014663     NA  0.8131974
    9  0.7284768    NA  0.857904
    




    我是这样做的:

    首先,我使用“plyr”来计算我的平均值,这很简单:

    test <- ddply(prf.delete2b,. (YYYYMMbucket), summarise, 
        NY1M = mean(NY1), NY2M = mean(NY2) ... ...))
    

    然后使用以下一系列:

    x <- c(1:40893)
    
    lookv <- function(x,ltab,rcol=2) ltab[max(which(ltab[,1]<=x)),rcol]
    
    NY1Fun <- function(x) (prf.delete2b$NY1[x] / lookv((prf.delete2b$YYYYMMbucket[x]),test,2))
    
    NY2Fun <- function(x) (prf.delete2b$NY2[x] / lookv((prf.delete2b$YYYYMMbucket[x]),test,3))
    
    NY1Avgs <- lapply(x, NY1Fun)
    NY2Avgs <- lapply(x, NY2Fun)
    

    我还尝试了以上的变体:

    NY1Fun <- function(x) (prf.delete2b$NY1[x] / subset(test, YYYYMMbucket == prf.delete2b$YYYYMMbucket[x], select =c(NY1M)))
    
    lapply(x, NY1Fun)
    

    NYnFun的每个变体都需要20秒才能运行,因此这样做300次需要花费太长时间。任何人都可以推荐任何替代我发布的内容或指出我所做的任何新手错误吗?

3 个答案:

答案 0 :(得分:3)

这是惯用的data.table方法,它的工作速度非常快。

# CREATE DUMMY DATA
N = 1000
mydf = data.frame(
  bucket = sample(letters, N, replace = T),
  NY1    = runif(N),
  NY2    = runif(N),
  NY3    = runif(N),
  NY4    = runif(N)
)

# SCALE COLUMNS BY AVG
library(data.table)
scale_x = function(x) x/ave(x)
mydt = data.table(mydf)
ans  = mydt[,lapply(.SD, scale_x), by = 'bucket']

答案 1 :(得分:0)

怎么样:

test2 <- merge(prfdelete2b,test,all.x=TRUE)
test2[2:ncol(prefdelete2b)]/test2[(ncol(prefdelete2b)+1):ncol(test2)]

答案 2 :(得分:0)

在这种情况下,我会使用ave而不是ddply,因为ave会返回与其输入长度相同的向量。 ave只接受一个向量,因此您需要使用lapply循环遍历data.frame的列。

myFun <- function(x, groupVar) {
  x / ave(x, groupVar, FUN=function(y) mean(y, na.rm=TRUE))
}
relToMeans <- data.frame(prf.delete2b[1],
  lapply(prf.delete2b[-1], myFun, groupVar=prf.delete2b[1]))