Как добавить строку во фрейм данных с итогами? - PullRequest
31 голосов
/ 09 февраля 2011

У меня есть фрейм данных, в который я хотел бы добавить дополнительную строку, которая суммирует значения для столбцов.Например, допустим, у меня есть эти данные:

x <- data.frame(Language=c("C++", "Java", "Python"), 
                Files=c(4009, 210, 35), 
                LOC=c(15328,876, 200), 
                stringsAsFactors=FALSE)    

Данные выглядят так:

  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200

Мой инстинкт должен сделать это:

y <- rbind(x, c("Total", colSums(x[,2:3])))

Иэто работает, он вычисляет итоги:

> y
  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
4    Total  4254 16404

Проблема в том, что все столбцы Files и LOC были преобразованы в строки:

> y$LOC
[1] "15328" "876"   "200"   "16404"

Я понимаю, что это происходит, потому что ясоздал вектор c("Total", colSums(x[,2:3]) с входными данными, которые являются как числами, так и строками, и он преобразует все элементы в общий тип, чтобы все элементы вектора были одинаковыми.Затем то же самое происходит с колонками Files и LOC.

Какой лучший способ сделать это?

Ответы [ 10 ]

23 голосов
/ 09 февраля 2011

Вот способ, который дает вам то, что вы хотите, но вполне может быть более элегантное решение.

rbind(x, data.frame(Language="Total",t(colSums(x[,-1]))))

Для протокола, я предпочитаю ответ Чейза, если вам абсолютно не нужен столбец Language.

23 голосов
/ 13 апреля 2018

См. adorn_totals() из пакета janitor:

library(janitor)
x %>%
  adorn_totals("row")

#>  Language Files   LOC
#>       C++  4009 15328
#>      Java   210   876
#>    Python    35   200
#>     Total  4254 16404

Числовые столбцы остаются числовыми в классе.

Отказ от ответственности: я создал этот пакет, включая adorn_totals()сделано именно для этой задачи.

20 голосов
/ 09 февраля 2011

Вам нужен столбец «Язык» в ваших данных или более уместно думать об этом столбце как row.names? Это изменит ваш data.frame с 4 наблюдений 3 переменных на 4 наблюдения 2 переменных (Files & LOC).

x <- data.frame(Files=c(4009, 210, 35), LOC=c(15328,876, 200), row.names=c("C++", "Java", "Python"), stringsAsFactors=F)    
x["Total" ,] <- colSums(x)


> x
       Files   LOC
C++     4009 15328
Java     210   876
Python    35   200
Total   4254 16404
14 голосов
/ 14 мая 2018

A tidyverse способ сделать это будет использовать bind_rows (или в конечном итоге add_rows) и summarise для вычисления сумм.Здесь проблема в том, что нам нужны суммы для всех, кроме одного, поэтому уловка будет:

summarise_all(x, funs(if(is.numeric(.)) sum(.) else "Total"))

В одной строке:

x %>%
  bind_rows(summarise_all(., funs(if(is.numeric(.)) sum(.) else "Total")))
9 голосов
/ 30 июля 2016

Попробуйте это

y[4,] = c("Total", colSums(y[,2:3]))
6 голосов
/ 09 февраля 2011

Если (1) нам не нужен заголовок "Language" в первом столбце, то мы можем представить его, используя имена строк, и если (2) можно пометить последнюю строку как "Sum", а не "Total" тогда мы можем использовать addmargins следующим образом:

rownames(x) <- x$Language
addmargins(as.table(as.matrix(x[-1])), 1)

, давая:

       Files   LOC
C++     4009 15328
Java     210   876
Python    35   200
Sum     4254 16404

Если мы хотим, чтобы первый столбец был помечен как "Language", а итоговая строка - как "Total"затем немного дольше:

rownames(x) <- x$Language
Total <- sum
xa <- addmargins(as.table(as.matrix(x[-1])), 1, FUN = Total)
data.frame(Language = rownames(xa), as.matrix(xa[]), row.names = NULL)

, что дает:

  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
4    Total  4254 16404
1 голос
/ 09 ноября 2014

Поскольку вы упоминаете, что это последний шаг перед экспортом для презентации, у вас могут быть имена столбцов, которые будут содержать пробелы в них для ясности (например, "Общий итог").Если это так, следующее гарантирует, что созданный data.frame будет привязан к исходному набору данных без ошибки, вызванной несовпадающими именами столбцов:

dfTotals <- data.frame(Language="Total",t(colSums(x[,-1]))))

colnames(dfTotals) <- names(x)  

rbind(x, dfTotals)
1 голос
/ 09 февраля 2011

Вы уверены, что действительно хотите иметь итоговые значения столбцов в вашем фрейме данных?Для меня интерпретация фрейма данных теперь зависит от строки.Например,

  • Строки 1- (n-1): сколько файлов связано с конкретным языком
  • Строка n: сколько файлов связанос всеми языками

Это становится более запутанным, если вы начинаете подмножество своих данных.Например, предположим, что вы хотите знать, какие языки имеют более 100 файлов:

> x = data.frame(Files=c(4009, 210, 35), 
                LOC=c(15328,876, 200), 
                row.names=c("C++", "Java", "Python"), 
                stringsAsFactors=FALSE)    
> x["Total" ,] = colSums(x)
> x[x$Files > 100,]
       Files   LOC
C++    4009 15328
Java    210   876
Total  4254 16404#But this refers to all languages!

Строка Total теперь неверна!

Лично я бы определил суммы столбцов и сохраниих в отдельном векторе.

0 голосов
/ 11 ноября 2017

Вы можете использовать apply для каждой суммы col

Apply (df [-колонки, которые вам не нужны в сумме], 2, sum)

И затемВы можете

rbind

эти данные в вашей DF

0 голосов
/ 09 февраля 2011

Ваш первоначальный инстинкт сработает, если вы приведете свои столбцы к числовому:

y$LOC <- as.numeric(y$LOC)
y$Files <- as.numeric(y$Files)

, а затем примените colSums () и rbind ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...