Накопленная сумма по группам в sqldf? - PullRequest
3 голосов
/ 19 декабря 2011

У меня есть фрейм данных с 3 переменными: место, время и значение (P, T, X). Я хочу создать четвертую переменную, которая будет кумулятивной суммой X. Обычно я люблю группировать вычисления с sqldf, но не могу найти эквивалент для cumsum. То есть:

sqldf("select P,T,X, cumsum(X) as X_CUM from df group by P,T") 

не работает. Возможно ли это даже с sqldf? Я пытался doBy, но это еще не все cumsum.

Ответы [ 3 ]

8 голосов
/ 19 декабря 2011

Настройте некоторые тестовые данные:

DF <- data.frame(t = 1:4, p = rep(1:3, each = 4), value = 1:12)

и теперь у нас есть три решения.Сначала мы используем sqldf в соответствии с запросом, используя базу данных SQLite по умолчанию.Затем мы снова делаем это с sqldf, но на этот раз с PostgreSQL, используя драйвер RPostgreSQL или RpgSQL .PostgreSQL поддерживает аналитические оконные функции, которые упрощают SQL.Для этого вам нужно сначала настроить базу данных PostgreSQL.Наконец, мы показываем решение на чистом R, которое использует только ядро ​​R.

1) sqldf / RSQLite

library(sqldf)

sqldf("select a.*, sum(b.value) as cumsum 
    from DF a join DF b 
    using (p)
    where a.t >= b.t
    group by p, a.t"
)

2) sqldf / RPostgreSQL

library(RPostgreSQL)
library(sqldf)

sqldf('select *,
    sum(value) over (partition by p order by t) as cumsum 
    from "DF"'
)

(Это также работает с драйвером RpgSQL PostgreSQL. Чтобы использовать это, у вас должна быть установлена ​​Java и настроена база данных PostgreSQL, а затем вместо вышеуказанного используйте: 1ibrary(RpgSQL); sqldf(...), где то же самоеСтрока SQL используется за исключением того, что в кавычках не должно быть DF.)

3) Обычный R

transform(DF, cumsum = ave(value, p, FUN = cumsum))
1 голос
/ 20 декабря 2011

Или другой вариант: data.table .

> library(data.table)
> DT = data.table(place = 1:4, time = rep(1:3, each = 4), value = 1:3)
> setkey(DT,place,time)   # order by place and time
> DT
      place time value
 [1,]     1    1     1
 [2,]     1    2     2
 [3,]     1    3     3
 [4,]     2    1     2
 [5,]     2    2     3
 [6,]     2    3     1
 [7,]     3    1     3
 [8,]     3    2     1
 [9,]     3    3     2
[10,]     4    1     1
[11,]     4    2     2
[12,]     4    3     3
> DT[,list(time,value,cumsum(value)),by=place]
      place time value V3
 [1,]     1    1     1  1
 [2,]     1    2     2  3
 [3,]     1    3     3  6
 [4,]     2    1     2  2
 [5,]     2    2     3  5
 [6,]     2    3     1  6
 [7,]     3    1     3  3
 [8,]     3    2     1  4
 [9,]     3    3     2  6
[10,]     4    1     1  1
[11,]     4    2     2  3
[12,]     4    3     3  6
> 
1 голос
/ 19 декабря 2011

Надеюсь, я понял, что вы хотите:

library(plyr)
ddply(df, .(P,T), summarize, cumsum(X))

это вам поможет?

...