R 以编程方式创建新变量,这些变量是其他变量嵌套系列的总和
我有数据显示某些群体中具有不同教育程度的人的百分比:R 以编程方式创建新变量,这些变量是其他变量嵌套系列的总和,r,dplyr,tidyverse,purrr,R,Dplyr,Tidyverse,Purrr,我有数据显示某些群体中具有不同教育程度的人的百分比: df <- data_frame(group = c("A", "B"), no.highschool = c(20, 10), high.school = c(70,40), college = c(10, 40), graduate = c(0,10)) df # A tibble: 2 x 5 group no.h
df <- data_frame(group = c("A", "B"),
no.highschool = c(20, 10),
high.school = c(70,40),
college = c(10, 40),
graduate = c(0,10))
df
# A tibble: 2 x 5
group no.highschool high.school college graduate
<chr> <dbl> <dbl> <dbl> <dbl>
1 A 20. 70. 10. 0.
2 B 10. 40. 40. 10.
df
如何使用tidyverse工具以编程方式(优雅地)实现这一点
当然,第一步是整理数据。列名中的编码信息(如edu级别)不整齐。当您将教育
转换为因子时,请确保级别的顺序正确-我使用了它们在原始数据列名称中出现的顺序
library(tidyr)
tidy_result = df %>% gather(key = "education", value = "n", -group) %>%
mutate(education = factor(education, levels = names(df)[-1])) %>%
group_by(group) %>%
mutate(lessthan_x = lag(cumsum(n), default = 0) / sum(n) * 100) %>%
arrange(group, education)
tidy_result
# # A tibble: 8 x 4
# # Groups: group [2]
# group education n lessthan_x
# <chr> <fct> <dbl> <dbl>
# 1 A no.highschool 20 0
# 2 A high.school 70 20
# 3 A college 10 90
# 4 A graduate 0 100
# 5 B no.highschool 10 0
# 6 B high.school 40 10
# 7 B college 40 50
# 8 B graduate 10 90
library(tidyr)
整理结果=df%>%gather(key=“education”、value=“n”、-group)%>%
突变(教育=因子(教育,等级=名称(df)[-1]))%>%
分组依据(分组)%>%
突变(lessthan_x=lag(累积和(n),默认值=0)/sum(n)*100)%>%
安排(团体、教育)
整洁的结果
##A tibble:8 x 4
##组:组[2]
#乐山市团体教育
#
#1 A第二中学20 0
#A高中70 20
#3 A学院10 90
#4一名毕业生0 100
#5 B第二中学10 0
#6 B高中40 10
#7 B学院40 50
#8 B毕业生10 90
这给了我们一个好的、整洁的结果。如果您想传播
/将这些数据转换成您不整洁的所需的.df
格式,我建议您使用data.table::dcast
,因为(据我所知)tidyverse不能提供传播多列的好方法。有关数据。表
解决方案或不雅观的tidyr
/dplyr
版本,请参阅或。在传播之前,您可以创建一个小于的密钥粘贴(“lessthan”,education,sep=“”)
,这里是一个基本的解决方案。虽然这个问题需要一个tidyverse
one,但考虑到问题评论中的对话,我决定发布它。
它使用apply
和cumsum
来完成艰苦的工作。然后,在cbind
进入最终结果之前,还有一些表面上的顾虑
tmp <- apply(df[-1], 1, function(x){
s <- cumsum(x)
100*c(0, s[-length(s)])/sum(x)
})
rownames(tmp) <- paste("lessthan", names(df)[-1], sep = "_")
desired.df <- cbind(df, t(tmp))
desired.df
# group no.highschool high.school college graduate lessthan_no.highschool
#1 A 20 70 10 0 0
#2 B 10 40 40 10 0
# lessthan_high.school lessthan_college lessthan_graduate
#1 20 90 100
#2 10 50 90
tmp没有低于no.highschool的级别,因此lessthan_no.highschool将始终为0。在desired.df
中,变量小于.hs
。难道不是吗?高中
?不知道你的意思吗?@lost Gregor抢先告诉我,在你想要的结果中,你重复输入的变量,因此它们的名称应该是相同的。其中一个不是。我以为这是个打字错误。哦,我错过了关于tidyverse的部分,所以我正忙着编写一个基本的R方式。有兴趣吗?那是个打字错误,对不起。修正了。它是故意用不整洁的格式。它采用这种格式是因为它将被连接到各个层次的数据中,这些数据的格式是整齐的,并且将用于建模等等。对,太好了。但是如果你想“优雅地”使用tidyverse
工具,你需要先整理一下。我链接的问题应该可以帮助你把它恢复到你需要的不整洁的格式。我不认为我需要在这里重复这些答案。如果有更改或更新,则应更新针对该问题的那些问题。虽然变量的顺序与OP中的不同,但这是可行的:desired.df%select(-n)%%>%mutate(education=paste0(“lessthan_u”,education))%%>%spread(education,lessthan_x)%%>%right_join(df)
tmp <- apply(df[-1], 1, function(x){
s <- cumsum(x)
100*c(0, s[-length(s)])/sum(x)
})
rownames(tmp) <- paste("lessthan", names(df)[-1], sep = "_")
desired.df <- cbind(df, t(tmp))
desired.df
# group no.highschool high.school college graduate lessthan_no.highschool
#1 A 20 70 10 0 0
#2 B 10 40 40 10 0
# lessthan_high.school lessthan_college lessthan_graduate
#1 20 90 100
#2 10 50 90