Разделение конкретных значений между двумя массивами - PullRequest
2 голосов
/ 15 сентября 2011

Я начинающий пользователь R, пытающийся работать с набором данных из 40000 строк и 300 столбцов.Я нашел решение для того, что я хотел бы сделать, однако моей машине требуется более часа, чтобы выполнить мой код, и я чувствую, что эксперт может помочь мне с более быстрым решением (поскольку я могу сделать это в Excel в два раза быстрее),В конце я опубликую свое решение.

Я хотел бы сделать следующее:

  1. Рассчитать среднее значение для каждого столбца NY1 - ​​NYn на основезначение столбца YYYYMMbucket.

  2. Разделите исходное значение на его среднее значение YYYYMMbucket.

Вот пример моего исходного набора данных:

     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 ]

3 голосов
/ 15 сентября 2011

Вот обычный 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']
0 голосов
/ 15 сентября 2011

В этом случае я бы использовал 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]))
0 голосов
/ 15 сентября 2011

Как насчет:

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