从长到宽重塑并创建具有二进制值的列
Posted
技术标签:
【中文标题】从长到宽重塑并创建具有二进制值的列【英文标题】:Reshape from long to wide and create columns with binary value 【发布时间】:2016-06-10 08:51:06 【问题描述】:我知道tidyr
包中的spread
函数,但这是我无法实现的。
我有一个data.frame
,其中包含如下定义的 2 列。我需要将Subject
列转置为具有 1 和 0 的二进制列。
下面是数据框:
studentInfo <- data.frame(StudentID = c(1,1,1,2,3,3),
Subject = c("Maths", "Science", "English", "Maths", "History", "History"))
> studentInfo
StudentID Subject
1 1 Maths
2 1 Science
3 1 English
4 2 Maths
5 3 History
6 3 History
我期待的输出是:
StudentID Maths Science English History
1 1 1 1 1 0
2 2 1 0 0 0
3 3 0 0 0 1
如何使用spread()
函数或任何其他函数来做到这一点。
【问题讨论】:
【参考方案1】:使用reshape2
,我们可以将dcast
从长到宽。
由于您只想要二元结果,我们可以先unique
数据
library(reshape2)
si <- unique(studentInfo)
dcast(si, formula = StudentID ~ Subject, fun.aggregate = length)
# StudentID English History Maths Science
#1 1 1 0 1 1
#2 2 0 0 1 0
#3 3 0 1 0 0
使用tidyr
和dplyr
的另一种方法是
library(tidyr)
library(dplyr)
studentInfo %>%
mutate(yesno = 1) %>%
distinct %>%
spread(Subject, yesno, fill = 0)
# StudentID English History Maths Science
#1 1 1 0 1 1
#2 2 0 0 1 0
#3 3 0 1 0 0
虽然我还不是 tidyr
语法的粉丝...
【讨论】:
【参考方案2】:我们可以从base R
使用table
+(table(studentInfo)!=0)
# Subject
#StudentID English History Maths Science
# 1 1 0 1 1
# 2 0 0 1 0
# 3 0 1 0 0
【讨论】:
哇,这是一种非常优雅的使用方式。但如果数据帧较大,它会给出类似“表错误:尝试使用 >= 2^31 个元素创建表”的消息 @sachinv 你可能已经超过了观察次数的限制。【参考方案3】:使用 tidyr :
library(tidyr)
studentInfo <- data.frame(
StudentID = c(1,1,1,2,3,3),
Subject = c("Maths", "Science", "English", "Maths", "History", "History"))
pivot_wider(studentInfo,
names_from = "Subject",
values_from = 'Subject',
values_fill = 0,
values_fn = function(x) 1)
#> # A tibble: 3 x 5
#> StudentID Maths Science English History
#> <dbl> <int> <int> <int> <int>
#> 1 1 1 1 1 0
#> 2 2 1 0 0 0
#> 3 3 0 0 0 1
由reprex package (v0.3.0) 于 2019 年 9 月 19 日创建
【讨论】:
这个解决方案很棒...您能否详细说明一下 ~+(as.logical(length(.)))))。具体来说,你能指出我在哪里可以找到更多关于使用“+”的文档?谢谢! 感谢thisisrg,这里+
会将逻辑转换为整数,+TRUE
为1。因此调用的结果始终为1,除非长度为零。
谢谢。 pivot_wider
创建虚拟变量实际上很复杂,但您的代码也帮助我使用 T/F 值做到这一点。我不得不将data.frame
更改为tibble
,没有它就无法工作,不知道为什么。 r studentInfo <- tibble(StudentID = c(1,1,1,2,3,3), Subject = c("Maths", "Science", "English", "Maths", "History", "History")) pivot_wider(studentInfo, names_from = Subject, values_from = Subject, values_fill = list(Subject = F), values_fn = list(Subject = is.character))
嗨,James,在我的系统上,无论我使用 data.frame 还是 tibble(R 和 tidyr 的最新发布版本),您的代码都会给出相同的输出。以上是关于从长到宽重塑并创建具有二进制值的列的主要内容,如果未能解决你的问题,请参考以下文章