如何向具有总计的数据框添加行?

Lor*_*ein 32 r dataframe

我有一个数据框,我想添加一个额外的行,总计列的值.例如,假设我有这些数据:

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

数据如下所示:

  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
Run Code Online (Sandbox Code Playgroud)

我的直觉是这样做:

y <- rbind(x, c("Total", colSums(x[,2:3])))
Run Code Online (Sandbox Code Playgroud)

这有效,它计算总数:

> y
  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
4    Total  4254 16404
Run Code Online (Sandbox Code Playgroud)

问题是Files和LOC列都已转换为字符串:

> y$LOC
[1] "15328" "876"   "200"   "16404"
Run Code Online (Sandbox Code Playgroud)

我知道这种情况正在发生,因为我创建了一个c("Total", colSums(x[,2:3])带有数字和字符串输入的向量,并且它将所有元素转换为通用类型,以便所有向量元素都相同.那么Files和LOC列也会发生同样的事情.

有什么更好的方法呢?

Sam*_*rke 30

adorn_totals()从门卫包中看到:

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

#>  Language Files   LOC
#>       C++  4009 15328
#>      Java   210   876
#>    Python    35   200
#>     Total  4254 16404
Run Code Online (Sandbox Code Playgroud)

数字列仍为数字类.

免责声明:我创建了这个包,其中包括adorn_totals()用于完成此任务的包.


Jos*_*ich 23

这是一种可以满足您需求的方式,但可能会有更优雅的解决方案.

rbind(x, data.frame(Language="Total",t(colSums(x[,-1]))))
Run Code Online (Sandbox Code Playgroud)

为了记录,如果你不完全需要Language专栏,我更喜欢Chase的回答.


Cha*_*ase 22

您是否需要数据中的语言列,或者将该列视为row.names?更合适?这会将您的data.frame从3个变量的4个观察变为2个变量的4个观察值(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
Run Code Online (Sandbox Code Playgroud)

  • 就个人而言,我不建议将数据存储在rownames中 - 这就是变量的用途! (17认同)
  • 什么是tidyverse等价物? (6认同)
  • 总的来说,我同意。我也倾向于遵循@csgillespie的建议,即不要在同一对象中混合原始数据和摘要统计信息。正如OP指出的,在这种情况下,这实际上不是问题,因为问题围绕数据的呈现而不是任何进一步的分析。 (2认同)

Mat*_*fou 17

一种tidyverse方法是使用bind_rows(或最终add_rows)并summarise计算总和.这里的问题是我们想要除了一个以外的所有的总和,所以一个技巧是:

summarise_all(x, funs(if(is.numeric(.)) sum(.) else "Total"))
Run Code Online (Sandbox Code Playgroud)

在一行中:

x %>%
  bind_rows(summarise_all(., funs(if(is.numeric(.)) sum(.) else "Total")))
Run Code Online (Sandbox Code Playgroud)


小智 12

扩展Nicolas Ratto的答案,如果您有更多可以使用的列

x %>% add_row(Language = "Total", summarise(., across(where(is.numeric), sum)))
Run Code Online (Sandbox Code Playgroud)


小智 9

试试这个

y[4,] = c("Total", colSums(y[,2:3]))
Run Code Online (Sandbox Code Playgroud)


G. *_*eck 6

如果(1)我们不需要"Language"第一列的标题,那么我们可以使用行名表示它,如果(2)可以标记最后一行"Sum"而不是"Total"那么我们可以addmargins像这样使用:

rownames(x) <- x$Language
addmargins(as.table(as.matrix(x[-1])), 1)
Run Code Online (Sandbox Code Playgroud)

赠送:

       Files   LOC
C++     4009 15328
Java     210   876
Python    35   200
Sum     4254 16404
Run Code Online (Sandbox Code Playgroud)

如果我们确实希望标记第一列"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)
Run Code Online (Sandbox Code Playgroud)

赠送:

  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
4    Total  4254 16404
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试这个

library(tibble)
x %>% add_row( Language="Total",Files = sum(.$Files),LOC = sum(.$LOC) )
Run Code Online (Sandbox Code Playgroud)