我有一个数据框,我想添加一个额外的行,总计列的值。例如,假设我有这些数据:
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列中发生同样的事情。
有什么更好的方法可以做到这一点?
答案 0 :(得分:23)
这是一种可以满足您需求的方式,但可能会有一个更优雅的解决方案。
rbind(x, data.frame(Language="Total",t(colSums(x[,-1]))))
如果您不完全需要Language
列,我更喜欢Chase的回答。
答案 1 :(得分:21)
请参阅janitor包中的adorn_totals()
:
library(janitor)
x %>%
adorn_totals("row")
#> Language Files LOC
#> C++ 4009 15328
#> Java 210 876
#> Python 35 200
#> Total 4254 16404
数字列仍为数字类。
免责声明:我创建了这个软件包,包括adorn_totals()
,它是为了完成这项任务而制作的。
答案 2 :(得分:20)
您是否需要数据中的语言列,或者将该列视为row.names
更合适?这会将您的data.frame从3个变量的4个观察变为2个变量的4个观察值(Files&amp; 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
答案 3 :(得分:14)
执行此操作的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")))
答案 4 :(得分:9)
试试这个
y[4,] = c("Total", colSums(y[,2:3]))
答案 5 :(得分:5)
如果(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
答案 6 :(得分:1)
您确定要确保数据框中的列总数吗?对我来说,数据框的解释现在取决于行。例如,
如果您开始对数据进行分组,这会让您感到更加困惑。例如,假设您想知道哪些语言有超过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
行现在错了!
我个人会计算列总和并将它们存储在一个单独的向量中。
答案 7 :(得分:1)
由于您提到这是导出演示文稿之前的最后一步,因此为了清晰起见,您可能会在列名中包含空格(即“Grand Total”)。如果是这样,以下内容将确保创建的data.frame将绑定到原始数据集,而不会由不匹配的列名称导致错误:
dfTotals <- data.frame(Language="Total",t(colSums(x[,-1]))))
colnames(dfTotals) <- names(x)
rbind(x, dfTotals)
答案 8 :(得分:1)
尝试一下
library(tibble)
x %>% add_row( Language="Total",Files = sum(.$Files),LOC = sum(.$LOC) )
答案 9 :(得分:1)
df %>% bind_rows(purrr::map_dbl(.,sum))
答案 10 :(得分:1)
扩展Nicolas Ratto的答案,如果你有更多的列,你可以使用
x %>% add_row(Language = "Total", summarise(., across(where(is.numeric), sum)))
答案 11 :(得分:0)
如果您将列强制为数字,原始本能就会起作用:
y$LOC <- as.numeric(y$LOC)
y$Files <- as.numeric(y$Files)
然后应用colSums()和rbind()。
答案 12 :(得分:0)
您可以使用申请每个总和
申请(df [ - 你不想要的总和],2,总和)
然后你可以
rbind
你df中的数据