Сгруппируйте/бин/базовые данные в R и получите количество значений на ведро и сумму значений на ведро

Я хочу ведро/группу/бин данные:

C1             C2       C3
49488.01172    0.0512   54000
268221.1563    0.0128   34399
34775.96094    0.0128   54444
13046.98047    0.07241  61000
2121699.75     0.00453  78921
71155.09375    0.0181   13794
1369809.875    0.00453  12312
750            0.2048   43451
44943.82813    0.0362   49871
85585.04688    0.0362   18947
31090.10938    0.0362   13401
68550.40625    0.0181   14345

Я хочу разделить его по значениям C2, но я хочу определить сегменты, например. ‹ = 0,005, ‹ = 0,010, ‹ = 0,014 и т. д. Как видите, интервалы разбиения будут неравномерными. Мне нужно количество C1 на ведро, а также общую сумму C1 для каждого ведра.

Я не знаю, с чего начать, поскольку я довольно новый пользователь R. Есть ли кто-нибудь, кто готов помочь мне разобраться в коде или указать мне пример, который будет работать для моих нужд?

РЕДАКТИРОВАТЬ: добавлен еще один столбец C3. Мне нужна сумма C3 на ведро, а также сумма и количество C1 на ведро


person Freewill    schedule 04.01.2015    source источник
comment
Обычно, когда вы делаете перекрестный пост, считается вежливым сообщить людям, что вы это сделали talkstats.com/showthread.php/   -  person Tyler Rinker    schedule 04.01.2015
comment
Спасибо, Тайлер, это два разных сайта, так что я бы не подумал, что это необходимо.   -  person Freewill    schedule 04.01.2015
comment
@user3007275 user3007275 Вы все еще хотите использовать C2 в качестве группирующей переменной?   -  person akrun    schedule 05.01.2015
comment
Да, C2 остается группирующей переменной   -  person Freewill    schedule 05.01.2015
comment
спасибо, akrun, интересно, как R в целом обрабатывает оператор do.call. Теперь, когда у вас есть две сгруппированные переменные C1 и C3, FUN по-прежнему использует только один оператор X вместо двух - по одному для C1 и C3. Какая здесь логика?   -  person Freewill    schedule 05.01.2015
comment
@user3007275 user3007275 Я думаю, вам нужно посмотреть на ?aggregate.formula, т.е. formula: a formula, such as ‘y ~ x’ or ‘cbind(y1, y2) ~ x1 + x2’, where the ‘y’ variables are numeric data to be split into groups according to the grouping ‘x’ variables (usually factors).   -  person akrun    schedule 05.01.2015
comment
спасибо, Акрун, я думаю, что теперь я понимаю это немного лучше. очень признателен.   -  person Freewill    schedule 05.01.2015


Ответы (1)


Судя по комментариям, «C2» кажется «символьным» столбцом с суффиксом %. Перед созданием группы удалите % с помощью sub, преобразуйте в "числовой" (as.numeric). Переменная «группа» создается (transform(df,...)) с помощью функции cut с аргументами breaks (групповые сегменты/интервалы) и labels (для нужных групповых меток). После создания групповой переменной sum "C1" по "группе" и "количество" элементов в "группе" можно выполнить с помощью aggregate из "базы R"

df1 <-  transform(df, group=cut(as.numeric(sub('[%]', '', C2)), 
    breaks=c(-Inf,0.005, 0.010, 0.014, Inf),
      labels=c('<0.005', 0.005, 0.01, 0.014)))

 res <- do.call(data.frame,aggregate(C1~group, df1, 
        FUN=function(x) c(Count=length(x), Sum=sum(x))))

 dNew <- data.frame(group=levels(df1$group))
 merge(res, dNew, all=TRUE)
 #   group C1.Count    C1.Sum
 #1 <0.005        2 3491509.6
 #2  0.005       NA        NA
 #3   0.01        2  302997.1
 #4  0.014        8  364609.5

или вы можете использовать data.table. setDT преобразует data.frame в data.table. Укажите переменную "grouping" с помощью by= и суммируйте/создайте две переменные "Count" и "Sum" в пределах list(. .N дает количество элементов в каждой "группе".

 library(data.table)
  setDT(df1)[, list(Count=.N, Sum=sum(C1)), by=group][]

Или используя dplyr. %>% соединяет аргументы LHS с аргументами RHS и связывает их вместе. Используйте group_by, чтобы указать переменную «группа», а затем используйте summarise_each или summarise, чтобы получить итоговое количество и sum соответствующего столбца. summarise_each было бы полезно, если есть более одного столбца.

 library(dplyr)
 df1 %>%
      group_by(group) %>% 
      summarise_each(funs(n(), Sum=sum(.)), C1)

Обновлять

Использование нового набора данных df

df1 <- transform(df, group=cut(C2,  breaks=c(-Inf,0.005, 0.010, 0.014, Inf),
                             labels=c('<0.005', 0.005, 0.01, 0.014)))

res <- do.call(data.frame,aggregate(cbind(C1,C3)~group, df1, 
       FUN=function(x) c(Count=length(x), Sum=sum(x))))
res
#  group C1.Count    C1.Sum C3.Count C3.Sum
#1 <0.005        2 3491509.6        2  91233
#2   0.01        2  302997.1        2  88843
#3  0.014        8  364609.5        8 268809

и вы можете сделать merge, как описано выше.

Подход dplyr будет таким же, за исключением указания дополнительной переменной

 df1%>%
      group_by(group) %>%
       summarise_each(funs(n(), Sum=sum(.)), C1, C3)
 #Source: local data frame [3 x 5]

 #  group C1_n C3_n    C1_Sum C3_Sum
 #1 <0.005    2    2 3491509.6  91233
 #2   0.01    2    2  302997.1  88843
 #3  0.014    8    8  364609.5 268809

данные

df <-structure(list(C1 = c(49488.01172, 268221.1563, 34775.96094, 
13046.98047, 2121699.75, 71155.09375, 1369809.875, 750, 44943.82813, 
85585.04688, 31090.10938, 68550.40625), C2 = c("0.0512%", "0.0128%", 
"0.0128%", "0.07241%", "0.00453%", "0.0181%", "0.00453%", "0.2048%", 
"0.0362%", "0.0362%", "0.0362%", "0.0181%")), .Names = c("C1", 
"C2"), row.names = c(NA, -12L), class = "data.frame")
person akrun    schedule 04.01.2015
comment
Спасибо, akrun, я тоже пытаюсь понять логику/смысл кода, который вы предоставили. Я нашел первый более простым для понимания, чем два других. Есть ли ресурс (книга/веб-сайт), на котором я могу следовать этим трем предложениям, чтобы понять, что происходит, и, возможно, посмотреть пример или два применения? - person Freewill; 04.01.2015
comment
Спасибо, я только что попробовал первое предложение. C2 на самом деле в процентах, поэтому, когда я помещаю знак % в breaks=c(-Inf,0,005%,0,10%,0,014%,Inf), я получаю сообщение об ошибке. Это работает, если знак % не используется. Кроме того, после биннинга мне нужно построить эти данные для гистограммы. Как я представляю категории, например. тот, у которого ‹=0,05, будет 0,05, ‹= 0,10 будет 0,10 и т. д. - person Freewill; 04.01.2015
comment
Акрун, спасибо. Я попробовал первый код, и он, похоже, сработал. Я еще раз проверю вывод. Одна вещь, которую я заметил, заключается в том, что если для данного бина нет значений, он пропускает этот бин из вывода. Я хотел бы иметь все ящики независимо от того, есть ли какие-либо значения или нет. - person Freewill; 04.01.2015
comment
Akrun, я только что заметил, что ваш код использует C2 как столбец символов. На самом деле это числовое значение (в %). Я просто хочу, чтобы он был помечен как процент, но данные были в своей форме как есть. Я использовал первый код, который вы опубликовали. Почему возникла необходимость создать новый набор данных, а затем объединить его со старым? что делает dNew? (логика этой части кода) - person Freewill; 04.01.2015
comment
@user3007275 user3007275 Но вы сказали, что данные имеют суффикс % (или я мог неправильно понять). Если это уже числовой столбец, вы можете использовать мой предыдущий код. dNew содержит все уровни, в то время как исходный набор данных может не иметь основанного на groupings. Таким образом, если конкретной группы нет, агрегат не вернет эту группу. При слиянии с dNew гарантируется получение и этой комбинации. - person akrun; 04.01.2015
comment
@user3007275 user3007275 Если вы хотите label как %, используйте paste, т.е. paste0(df1$group, '%') - person akrun; 04.01.2015
comment
Отлично, я попробовал dNew и слияние, и в итоге он создал новый набор данных с большим количеством наблюдений, чем исходный набор данных с NA для тех, где данные не существуют. Кроме того, когда я строю графики, они не получаются точными/чистыми, и R удаляет некоторые строки со ссылкой на отсутствующие значения. Есть ли другой способ получить эти мусорные ведра с первой попытки? - person Freewill; 04.01.2015
comment
@user3007275 user3007275 Я не уверен, какие значения вам нужны для этих missing combinations. Если это 0, просто замените NA этим. - person akrun; 04.01.2015
comment
Akrun, пытаюсь понять использование do.call в коде. Я довольно поверхностно понимаю, что do.call вызывает функцию, т.е. агрегат. Агрегат объединяет C1 по переменной «группа» в кадре данных df1. Но какова цель включения data.frame в функцию do.call и почему у нас есть FUN, определенный в агрегате. Я просмотрел структуру агрегатной функции в Интернете, но я не понимаю, как do.call и агрегат используются по отдельности и как они используются здесь вместе. Не могли бы вы направить меня к хорошему ресурсу, чтобы понять это? или дать какое-то объяснение? - person Freewill; 04.01.2015
comment
Кроме того, с функцией FUN, почему не используются фигурные скобки и что такое переменная «x»? мы никогда не вызываем эту переменную и не определяем ее, так как же R считает длину и суммирует эту переменную, не зная явно, о какой переменной мы говорим. Я имею в виду, что мы никогда не говорим явно, что x = C1. Что, если бы я хотел сгруппировать C1 по переменной «группа», а затем хотел бы получить сумму и количество C1, а также другую переменную, скажем, C3. - person Freewill; 04.01.2015
comment
@user3007275 user3007275 Что касается вашего первого комментария, поскольку мы использовали c(Count=length(x), Sum=sum(x)), результатом должна быть матрица для 3-го столбца. Проверь это. ` res ‹- агрегат(C1~group, df1, FUN=function(x) c(Count=length(x), Sum=sum(x))); str(res). The do.call(data.frame,..` преобразует матрицу в data.frame, и вы получите 4 обычных столбца вместо 3 столбцов. - person akrun; 05.01.2015
comment
@user3007275 user3007275 Это в формуле aggregate(C1~group....Если вы хотите оба C1 and C3, возможно, aggregate(cbind(C1,C3)~group,.. Ожидаемый результат для меня не ясен. Возможно, вам придется опубликовать пример набора данных. Кроме того, если вопрос не связан с вашим исходным сообщением, пожалуйста, опубликуйте его как отдельный. - person akrun; 05.01.2015
comment
Akrun, я добавил третий столбец C3 в набор данных. Мне также нужна сумма C3 на ведро в дополнение к сумме И количеству C1 на ведро, которое уже генерируется вашим кодом. - person Freewill; 05.01.2015
comment
akrun, я только что проверил res‹-aggregate(C1~group,df1,FUN=function(x) c(Count=length(x), Sum=sum(x))); str(res) и показывает res как фрейм данных, а не как матрицу. - person Freewill; 05.01.2015
comment
@user3007275 user3007275 Проверьте str(res). Вы увидите, что столбец C1 равен matrix.is.matrix(res$C1)#[1] TRUE - person akrun; 05.01.2015