Суммирование некоторых элементов кадра данных [duplicate]

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

253
задан David Arenburg 19 October 2015 в 08:57
поделиться

10 ответов

Используя aggregate:

aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
  Category  x
1    First 30
2   Second  5
3    Third 34

(вложение комментария @thelatemail), aggregate также имеет интерфейс формулы

aggregate(Frequency ~ Category, x, sum)

Или, если вы хотите для объединения нескольких столбцов вы можете использовать нотацию . (работает для одного столбца тоже)

aggregate(. ~ Category, x, sum)

или tapply:

tapply(x$Frequency, x$Category, FUN=sum)
 First Second  Third 
    30      5     34 

Используя эти данные:

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                      "Third", "Third", "Second")), 
                    Frequency=c(10,15,5,2,14,20,3))
266
ответ дан Gregor 17 August 2018 в 23:00
поделиться
  • 1
    @AndrewMcKinlay, R использует тильду для определения символических формул, для статистики и других функций. Его можно интерпретировать как «Модель по категориям» или «Частота, зависящая от категории» . Не все языки используют специальный оператор для определения символической функции, как это сделано в R здесь. Возможно, с этой "интерпретацией на естественном языке" оператора тильды, он становится более значимым (и даже интуитивным). Я лично считаю это символическое представление формул лучше, чем некоторые из более подробных альтернатив. – r2evans 19 December 2016 в 05:35
  • 2
    – Dodecaphone 28 October 2018 в 11:42

Ответ, предоставленный rcs, работает и прост. Однако, если вы работаете с большими наборами данных и нуждаетесь в повышении производительности, существует более быстрая альтернатива:

library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"), 
                  Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
#    Category V1
# 1:    First 30
# 2:   Second  5
# 3:    Third 34
system.time(data[, sum(Frequency), by = Category] )
# user    system   elapsed 
# 0.008     0.001     0.009 

Давайте сравним это с тем же, используя data.frame и выше:

data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
                  Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user    system   elapsed 
# 0.008     0.000     0.015 

И если вы хотите сохранить столбец, это синтаксис:

data[,list(Frequency=sum(Frequency)),by=Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

Разница станет более заметной с более крупными наборами данных, как показывает следующий код:

data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
                  Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user    system   elapsed 
# 0.055     0.004     0.059 
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000), 
                  Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user    system   elapsed 
# 0.287     0.010     0.296 

Для множественных агрегаций вы можете комбинировать lapply и .SD следующим образом

data[, lapply(.SD, sum), by = Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34
55
ответ дан Axeman 17 August 2018 в 23:00
поделиться
  • 1
    +1 Но 0,296 против 0,059 не особенно впечатляет. Размер данных должен быть намного больше, чем 300 тыс. Строк, и с более чем 3 группами, для того, чтобы data.table отображался. Например, мы попытаемся поддерживать более 2 миллиардов строк, так как некоторые пользователи данных.table имеют 250 ГБ оперативной памяти, а GNU R теперь поддерживает длину & ​​gt; 2 ^ 31. – Matt Dowle 9 September 2013 в 11:05
  • 2
    Правда. Оказывается, у меня нет всей этой ОЗУ, и она просто пыталась предоставить некоторые доказательства превосходной производительности data.table. Я уверен, что разница будет еще больше с большим количеством данных. – asieira 24 October 2013 в 00:22
  • 3
    У меня было 7 миллионов наблюдений, которые dplyr взял .3 секунды, и aggregate () занял 22 секунды, чтобы завершить операцию. Я собирался опубликовать его на эту тему, и вы избили меня! – zazu 14 November 2015 в 20:10
  • 4
    Существует еще более короткий способ написать это data[, sum(Frequency), by = Category]. Вы можете использовать .N, который заменяет функцию sum(). data[, .N, by = Category]. Вот полезная таблица: s3.amazonaws.com/assets.datacamp.com/img/blog/… – Stophface 22 February 2017 в 12:47
  • 5

Это несколько , связанное с этим вопросом .

Вы также можете просто использовать функцию by () :

x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))

Эти другие пакеты (plyr, reshape) имеют преимущество в возврате данных .frame, но это стоит знать с помощью (), поскольку это базовая функция.

33
ответ дан Community 17 August 2018 в 23:00
поделиться

Просто добавьте третий вариант:

require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)

EDIT: это очень старый ответ. Теперь я бы рекомендовал использовать group_by и суммировать из dplyr, как в ответе @docendo.

15
ответ дан dalloliogm 17 August 2018 в 23:00
поделиться

Несколько лет спустя просто добавить еще одно простое базовое R-решение, которое по какой-то причине отсутствует здесь xtabs

xtabs(Frequency ~ Category, df)
# Category
# First Second  Third 
#    30      5     34 

Или, если хотите data.frame назад

as.data.frame(xtabs(Frequency ~ Category, df))
#   Category Freq
# 1    First   30
# 2   Second    5
# 3    Third   34
17
ответ дан David Arenburg 17 August 2018 в 23:00
поделиться

Совсем недавно вы также можете использовать пакет dplyr для этой цели:

library(dplyr)
x %>% 
  group_by(Category) %>% 
  summarise(Frequency = sum(Frequency))

#Source: local data frame [3 x 2]
#
#  Category Frequency
#1    First        30
#2   Second         5
#3    Third        34

Или для нескольких суммарных столбцов (работает с одним столбцом тоже):

x %>% 
  group_by(Category) %>% 
  summarise_each(funs(sum))

Обновление для dplyr> = 0.5: summarise_each было заменено на семейство функций summarise_all, summarise_at и summarise_if в dplyr.

Или, если у вас есть несколько столбцов для группировки, вы можете указать все из них в group_by, разделенные запятыми:

mtcars %>% 
  group_by(cyl, gear) %>%                            # multiple group columns
  summarise(max_hp = max(hp), mean_mpg = mean(mpg))  # multiple summary columns

Для получения дополнительной информации, включая оператор %>%, см. введение в dplyr .

136
ответ дан docendo discimus 17 August 2018 в 23:00
поделиться
  • 1
    Насколько быстро это сравнивается с таблицами data.table и совокупными альтернативами, представленными в других ответах? – asieira 23 January 2015 в 15:35
  • 2
    @asieira, которая является самой быстрой и насколько велика разница (или если разница заметна) всегда будет зависеть от вашего размера данных. Как правило, для больших наборов данных, например, некоторых GB, data.table, скорее всего, будет быстрее всего. При меньших размерах данных, data.table и dplyr часто близки, также в зависимости от количества групп. Однако данные, таблица и dplyr будут намного быстрее, чем базовые функции, но могут быть в 100-1000 раз быстрее для некоторых операций. Также см. здесь – docendo discimus 23 January 2015 в 15:50

, используя cast вместо recast (примечание 'Frequency' теперь 'value')

df  <- data.frame(Category = c("First","First","First","Second","Third","Third","Second")
                  , value = c(10,15,5,2,14,20,3))

install.packages("reshape")

result<-cast(df, Category ~ . ,fun.aggregate=sum)

, чтобы получить:

Category (all)
First     30
Second    5
Third     34
1
ответ дан gps 17 August 2018 в 23:00
поделиться

Хотя я недавно стал конвертером в dplyr для большинства этих типов операций, пакет sqldf по-прежнему очень хорош (и IMHO более читабельным) для некоторых вещей.

Вот пример того, как можно ответить на этот вопрос с помощью sqldf

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                  "Third", "Third", "Second")), 
                Frequency=c(10,15,5,2,14,20,3))

sqldf("select 
          Category
          ,sum(Frequency) as Frequency 
       from x 
       group by 
          Category")

##   Category Frequency
## 1    First        30
## 2   Second         5
## 3    Third        34
14
ответ дан joemienko 17 August 2018 в 23:00
поделиться
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))
19
ответ дан learnr 17 August 2018 в 23:00
поделиться

Если x - это кадр данных с вашими данными, то следующее будет делать то, что вы хотите:

require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)
13
ответ дан Rob Hyndman 17 August 2018 в 23:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: