Вопрос

У меня есть кадр данных с 900 000 строк и 11 столбцов в R. Имена и типы столбцов следующие:

column name: date / mcode / mname / ycode / yname / yissue  / bsent   / breturn / tsent   / treturn / csales
type:        Date / Char  / Char  / Char  / Char  / Numeric / Numeric / Numeric / Numeric / Numeric / Numeric

Я хочу рассчитать подтолаты. Например, я хочу рассчитать суммы при каждом изменении в Yname и добавить подтота ко всем численным переменным. Есть 160 различных Ynames, поэтому полученная таблица должна сказать мне подтота каждого Yname. Я еще не отсортировал данные, но это не проблема, потому что я могу сортировать данные так, как я хочу. Ниже приведен фрагмент из моих данных:

             date     mcode mname            ycode    yname   yissue bsent breturn tsent treturn csales
417572 2010-07-28     45740 ENDPOINT A        5772    XMAG  20100800     7       0     7       0      0
417573 2010-07-31     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417574 2010-08-04     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417575 2010-08-14     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417576 2010-08-26     45740 ENDPOINT A        5772    XMAG  20100800     0       4     0       0      0
417577 2010-07-28     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417578 2010-08-04     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417579 2010-08-26     45741 ENDPOINT L        5772    XMAG  20100800     0       4     0       0      0
417580 2010-07-28     46390 ENDPOINT R        5772    XMAG  20100800     3       0     3       0      1
417581 2010-07-29     46390 ENDPOINT R        5772    XMAG  20100800     0       0     0       0      2
417582 2010-08-01     46390 ENDPOINT R        5779    YMAG  20100800     3       0     3       0      0
417583 2010-08-11     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417584 2010-08-20     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417585 2010-08-24     46390 ENDPOINT R        5779    YMAG  20100800     2       0     2       0      1
417586 2010-08-26     46390 ENDPOINT R        5779    YMAG  20100800     0       2     0       2      0
417587 2010-07-28     46411 ENDPOINT D        5779    YMAG  20100800     6       0     6       0      0
417588 2010-08-08     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417589 2010-08-11     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417590 2010-08-26     46411 ENDPOINT D        5779    YMAG  20100800     0       4     0       4      0

Какую функцию мне здесь следует использовать? Может что -то вроде SQL group by?

Это было полезно?

Решение

ХОРОШО. Предполагая, что ваши данные находятся в названном кадре данных foo:

> head(foo)
             date mcode      mname ycode yname   yissue bsent breturn tsent
417572 2010/07/28 45740 ENDPOINT A  5772  XMAG 20100800     7       0     7
417573 2010/07/31 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417574 2010/08/04 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417575 2010/08/14 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417576 2010/08/26 45740 ENDPOINT A  5772  XMAG 20100800     0       4     0
417577 2010/07/28 45741 ENDPOINT L  5772  XMAG 20100800     2       0     2
       treturn csales
417572       0      0
417573       0      1
417574       0      1
417575       0      1
417576       0      0
417577       0      0

Тогда это сделает агрегацию числовых столбцов в ваших данных:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum)
  yname bsent breturn tsent treturn csales
1  XMAG    14       8    14       0      6
2  YMAG    11       6    11       6      5

Который использовал фрагмент данных, которые вы включили в свой Q. Я использовал интерфейс формулы для aggregate(), что немного приятнее в этом случае, потому что вам не нужно все foo$ Биты на имена переменных, которые вы желаете заполнить. Если у вас отсутствуют данные (NA) в вашем полном наборе данных, то вам нужно добавить дополнительный аргумент na.rm = TRUE который будет передан sum(), вот так:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum, na.rm = TRUE)

Другие советы

Или plyr Библиотека, которая легко расширяется для других классов данных:

> library(plyr)
> result.2 <- ddply(df$a, .(df$b), sum)
> result.2
  df.b V1
1 down 30
2   up 25

Вы также можете использовать xtabs или tapply:

xtabs(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data)

tapply(data$bsent, data$yname, sum)

Если ваши данные имеют большие значения и скорость, я бы порекомендовал использовать rowsum rowsum, который намного быстрее. Я применил 3 метода (F1 = агрегат, f2 = ddply, f3 = tapply), предложенный в ответах, чтобы сравнить его с f4 = orowsum, а вот что я нахожу:

   test replications elapsed relative
4 f4()          100   0.033     1.00
3 f3()          100   0.046     1.39
1 f1()          100   0.165     5.00
2 f2()          100   0.605    18.33

Я добавил свой код ниже, если кто -то хочет изучить более подробно.

library(plyr);
library(rbenchmark);

val  = rnorm(50);
name = rep(letters[1:5], each = 10);
data = data.frame(val, name);

f1 = function(){aggregate(data$val, by=list(data$name), FUN=sum)}
f2 = function(){ddply(data, .(name), summarise, sum = sum(val))}
f3 = function(){tapply(data$val, data$name, sum)}
f4 = function(){rowsum(x = data$val, group = data$name)}

benchmark(f1(), f2(), f3(), f4(),
          columns=c("test", "replications", "elapsed", "relative"),
          order="relative", replications=100)

Ты можешь использовать aggregate

Например, скажем, что у вас есть

val = rnorm(50)
name = rep(letters[1:5], each=10)
data <- data.frame(val, name)

Тогда вы можете сделать

aggregate(data$val, by=list(data$name), FUN=sum)

Существует пакет R, который называется SQLDF, который позволяет использовать команды SQL на R Data.Frames. Кроме того, как вы уже сказали, Group By была бы хорошей. Вы можете легко сохранить свои данные в локальной базе данных MySQL и подключиться к R, используя пакет RMYSQL (вы можете использовать большинство других СУБД, но MySQL - самый простой для настройки).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top