Группировка данных в R (сродни суммированию с предложением WHERE в SQL) - PullRequest
2 голосов
/ 31 августа 2011

У меня проблема с группировкой данных в R с помощью команды aggregate . Я могу сделать это с помощью SQL относительно легко, но я не могу получить тот же эффект с R.

В качестве примера, вот тестовый набор данных, который в SQL обеспечивает суть того, что я ищу:

create table #data(v1 varchar(4), v2 int, v3 int, v4 int,v5 int)
insert #data(v1, v2, v3, v4, v5) values(8000, 3, 8, 7, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 4, 9, 8, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 5, 10, 9, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 6, 11, 7, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 7, 12, 8, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 3, 13, 9, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 4, 14, 7, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 5, 8, 8, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 6, 9, 9, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 7, 10, 7, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 3, 11, 8, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 4, 12, 9, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 5, 13, 7, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 6, 14, 8, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 7, 8, 9, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 3, 9, 7, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 4, 10, 8, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 5, 11, 9, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 6, 12, 7, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 7, 13, 8, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 3, 14, 9, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 4, 8, 7, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 5, 9, 8, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 6, 10, 9, 14)
insert #data(v1, v2, v3, v4, v5) values(8000, 7, 11, 7, 11)
insert #data(v1, v2, v3, v4, v5) values(8001, 3, 12, 8, 12)
insert #data(v1, v2, v3, v4, v5) values(8002, 4, 13, 9, 13)
insert #data(v1, v2, v3, v4, v5) values(8003, 5, 14, 7, 14)

select * from #data

select v1, sum(v2)
from #data
    where v4 <= v3 and v5 > v3
group by v1

drop table #data

В R я пытался использовать агрегат с командой subset , агрегат со встроенной функцией (x) ... и до сих пор не был в состоянии объединить данные так, как я надеялся, просто «R». Мне известна библиотека SQL, позволяющая передавать операторы SQL на структуру данных, но я стараюсь избегать этого, поскольку я в первую очередь извлекаю данные из базы данных, и если мне нужно прибегнуть к этому, я может также написать SQL, чтобы сделать это. Я ищу пурист R способ сделать это. Возможно, это немного идеалистично, но это надежда и мечта.

Что-то, что следует отметить с этим предложением, это что-то вроде исключительного предложения, суммирующего данные, НЕ включенные в переменную V2 в текущей строке. Если бы это было иначе, это было бы довольно простой проблемой для меня, но я не собираюсь передавать текущую строку под значениями проверки функции в сравнении с большим набором данных, или если вообще было бы лучше другое решение.

Заранее спасибо за помощь.

Вот код R для генерации тестовых данных:

m.data <- as.data.frame(
        cbind(8000:8003, 3:7, 8:14, 7:9, 11:14, 1:28),
        row.names=NULL
);

Ответы [ 2 ]

4 голосов
/ 31 августа 2011

Вот игрушечный пример, иллюстрирующий то, что Гэвин описал в комментариях:

dd <- data.frame(v1 = rep(1:4,5),v2 = 1:20, 
                 v3 = runif(20), v4 = runif(20), v5 = runif(20))

#Extract the subset
dd_new <- subset(dd,v4 <= v3 & v5 > v3)

#Using the aggregate command...
> aggregate(dd_new$v2,list(v1=dd_new$v1),sum)
  v1  x
1  1 14
2  2 18
3  3 41
4  4 16

#Or the often popular ddply from plyr
> ddply(dd_new,.(v1),summarise,tot = sum(v2))
  v1 tot
1  1  14
2  2  18
3  3  41
4  4  16

Я отделил подмножество от агрегирования для ясности, но, как указал Гэвин, вы можете свернуть все это в одну строку, если выкак.

1 голос
/ 31 августа 2011

А если вы SQL-наркоман, попробуйте sqldf. Это очень эффективно с большими наборами данных. Обратите внимание, что я использовал mdata вместо m.data, который необходимо экранировать в SQL.

library(sqldf)
mdata <- as.data.frame(
        cbind(8000:8003, 3:7, 8:14, 7:9, 11:14, 1:28),
        row.names=NULL
);
sqldf("select v1, sum(v2) from mdata  where v4 <= v3 and v5 > v3 group by v1")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...