我想为以下问题提供一个 tidyverse 解决方案。在我的数据集中,我有各种因素水平的数据。我想创建一个新的因子水平“总计”,它是 X 的现有因子水平下所有值 Y 的总和。这可以通过以下方式完成,例如:
mutate(Data, X = fct_collapse(X, Total = c("A", "B", "C", "D"))) %>%
group_by(X) %>%
summarize(Y = sum(Y))
但是,这也必然会覆盖原始因子水平。我将不得不在一个额外的步骤中将原始数据集与新的折叠数据集结合起来。
我过去用来保留原始级别的一个解决方案是将数据引入宽格式并继续使用
rowwise()
和 mutate()
创建一个带有“总计”的新变量,然后重塑回长格式。
spread(Data, key = X, value = Y) %>%
rowwise() %>%
mutate(Total = sum(A, B, C, D)) %>%
gather(1:5, key = "X", value = "Y")
但是,我对这个解决方案非常不满意,因为使用
rowwise()
不被认为是好的做法。如果您能指出一个可用的替代解决方案,如何在保留原始水平的同时合并不同因素水平下的数据,那就太好了。
最小可重现示例:
Data<-data.frame(
X = factor(c("A", "B", "C", "D")),
Y = c(1000, 2000, 3000, 4000))
预期结果:
# A tibble: 5 x 2
X Y
<chr> <dbl>
1 A 1000
2 B 2000
3 C 3000
4 D 4000
5 Total 10000
使用 janitor 库,这会很简单。
Data %>% janitor::adorn_totals("row") %>% mutate(X=factor(X))
# X Y
# A 1000
# B 2000
# C 3000
# D 4000
# Total 10000
查看输出结构:
str(output)
# 'data.frame': 5 obs. of 2 variables:
# $ X: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
# $ Y: num 1000 2000 3000 4000 10000
使用@M-- 对问题的第一个版本评论 中的建议,现在已编辑,我添加了
bind_rows
."Z"
,但保留原始顺序并在末尾添加级别"Total"
。
Data <- data.frame(
X = factor(c("A", "B", "C", "Z")),
Y = c(1000, 2000, 3000, 4000))
Data %>%
mutate(lvl = levels(X),
X = fct_collapse(X, Total = c("A", "B", "C", "Z")),
X = as.character(X)) %>%
bind_rows(mutate(Data, X = as.character(X)), .) %>%
mutate(X = factor(X, levels = c(lvl, "Total"))) %>%
group_by(X) %>%
summarize(Y = sum(Y)) -> d
d
## A tibble: 5 x 2
# X Y
# <fct> <dbl>
#1 A 1000
#2 B 2000
#3 C 3000
#4 Z 4000
#5 Total 10000
检查输出因子水平。
levels(d$X)
#[1] "A" "B" "C" "Z" "Total"
这个解决方案也可以用在这种情况下:
library(dplyr)
Data %>%
add_row(X = "Total", Y = sum(.$Y)) %>%
mutate(X = factor(X))
X Y
1 A 1000
2 B 2000
3 C 3000
4 D 4000
5 Total 10000
Data %>%
add_row(X = "Total", Y = sum(.$Y)) %>%
mutate(X = factor(X)) %>%
{levels(.$X)}
[1] "A" "B" "C" "D" "Total"