R 将行添加到数据框中,每列的总和为

R 将行添加到数据框中,每列的总和为,r,dataframe,R,Dataframe,我有一个数据框,我想在其中添加一个额外的行,该行汇总每个列的值。例如,假设我有以下数据: x <- data.frame(Language=c("C++", "Java", "Python"), Files=c(4009, 210, 35), LOC=c(15328,876, 200), stringsAsFactors=FALSE) 我的本能是这样做: y <- rbin

我有一个数据框,我想在其中添加一个额外的行,该行汇总每个列的值。例如,假设我有以下数据:

x <- data.frame(Language=c("C++", "Java", "Python"), 
                Files=c(4009, 210, 35), 
                LOC=c(15328,876, 200), 
                stringsAsFactors=FALSE)    
我的本能是这样做:

y <- rbind(x, c("Total", colSums(x[,2:3])))
问题是文件和LOC列都已转换为字符串:

> y$LOC
[1] "15328" "876"   "200"   "16404"
我知道这是因为我创建了一个向量
c(“Total”,colSums(x[,2:3])
,输入是数字和字符串,它将所有元素转换为一个公共类型,这样所有向量元素都是相同的。然后,相同的事情发生在文件和LOC列上


有什么更好的方法可以做到这一点?

您的数据中是否需要Language列,或者将该列视为将data.frame从3个变量的4个观察值更改为2个变量的4个观察值(Files&LOC)的
行名称更合适


x这里有一种方法可以满足您的需求,但很可能有一种更优雅的解决方案

rbind(x, data.frame(Language = "Total", t(colSums(x[, -1]))))
为了记录在案,如果你不绝对需要
语言
列,我更喜欢蔡斯的答案。

如果(1)我们不需要第一列的
“语言”
标题,那么我们可以使用行名来表示它,如果(2)可以将最后一行标记为
“Sum”
,而不是
“Total”
然后我们可以像这样使用
addmargins

  Language Files   LOC
1      C++  4009 15328
2     Java   210   876
3   Python    35   200
rownames(x) <- x$Language
addmargins(as.table(as.matrix(x[-1])), 1)
如果我们确实希望第一列标记为
“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)

您确定要在数据框中包含列总计吗?对我来说,数据框的解释现在取决于行。例如

  • 第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
行现在是错误的


就我个人而言,我会计算出列和,并将它们存储在一个单独的向量中。

如果将列强制为数字,您的原始直觉就会起作用:

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

y$LOC由于您提到这是导出以供演示之前的最后一步,为了清晰起见,您可能会有包含空格的列名(即“总计”)。如果是这样,以下内容将确保创建的data.frame将返回到原始数据集,而不会因列名不匹配而导致错误:

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

colnames(dfTotals) <- names(x)  

rbind(x, dfTotals)
dfTotals试试这个

y[4,] = c("Total", colSums(y[,2:3]))
library(tibble)
x %>% add_row( Language="Total",Files = sum(.$Files),LOC = sum(.$LOC) )
请参阅看门人软件包中的
装饰总计()

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

#>  Language Files   LOC
#>       C++  4009 15328
#>      Java   210   876
#>    Python    35   200
#>     Total  4254 16404
数值列仍然属于numeric类


免责声明:我创建了这个软件包,包括专门为这个任务设计的
adorn_totals()

一个
tidyverse
方法是使用
bind_rows
(或者最终
add_row
)和
总结
来计算总和。这里的问题是,除了一个,我们需要所有的总和,所以一个技巧是:

summarise_all(x, ~if(is.numeric(.)) sum(.) else "Total")
一行:

x %>%
  bind_rows(summarise_all(., ~if(is.numeric(.)) sum(.) else "Total"))
使用dplyr>=1.0进行编辑 还可以使用
cross()

x %>%
  bind_rows(summarise(.,
                      across(where(is.numeric), sum),
                      across(where(is.character), ~"Total")))
试试这个

y[4,] = c("Total", colSums(y[,2:3]))
library(tibble)
x %>% add_row( Language="Total",Files = sum(.$Files),LOC = sum(.$LOC) )
扩展的答案,如果你有更多的列,你可以使用

x %>% add_row(Language = "Total", summarise(., across(where(is.numeric), sum)))

就个人而言,我不建议将数据存储在行名中——这就是变量的用途!一般来说,我同意。我也倾向于遵循@csgillespie的建议,不要在同一个对象中混合原始数据和汇总统计数据。然而,正如OP所指出的,在这种情况下,这并不是一个真正的问题,因为问题围绕着dat的表示a、 没有任何进一步的分析。tidyverse等价物是什么?通常我不会这样做是为了分析,但这是为了演示。这是使用Swave在LaTeX文档中生成表之前的最后一步。谢谢,你是对的:我的解决方案不是必需的答案。你的答案是正确的。我投票支持你并删除了我的条目。很好,我很感激将其保存在
tidyverse
中,仅为此加载另一个包似乎很愚蠢。回答很好,为什么只对特定数量的列求和,因为其他列可能不需要求和,而是求平均值。我担心,如果要在不同的列上使用不同的函数,则需要手动运行
summaryse(var1=mean(var1),var2=sum(var2),var=“Total”)
sure@SashaPoda,done!这是一个很好的解决方案,但您必须删除第一列,然后将其传递给map_dbl。一种方法是使用[]运算符。x%>%bind_行(x[,-1]>%map_dbl(,sum))
library(tibble)
x %>% add_row( Language="Total",Files = sum(.$Files),LOC = sum(.$LOC) )
df %>% bind_rows(purrr::map_dbl(.,sum))
x %>% add_row(Language = "Total", summarise(., across(where(is.numeric), sum)))