将一列变量和一列值分隔为r中的组件

时间:2018-04-09 15:34:29

标签: r list dataframe dplyr tidyr

我有以下数据框(df),对于每个参与者,列"等级"是通过粘贴一些项目的分数来建立的。例如,参与者' 1'已经获得4个项目' a' 7项目' b'和8项目' c'。 (注意成绩是一个角色)。另请注意参与者' 2'只有两个分数(假设这是一个与参与者不同的分数' 1)。

df = data.frame(participants = c(1, 1, 2),
                variables = c('abc', 'ef', 'abc'),
                grades= c('478', '58', '942'),
                stringsAsFactors = FALSE)


 participants variables grades
1            1       abc    478
2            1        ef     58
3            2       abc    942

(我的数据包含100,000行,如上所述。)

我希望将数据转换为整洁的样式,如下所示:

  participants variables grades
1            1         a      4
2            1         b      7
3            1         c      8
4            1         e      5
5            1         f      8
6            2         a      9
7            2         b      4
8            2         c      2

我在这里做了什么

variables =  lapply(X=1:length(df$variables), FUN=function(X) {
  strsplit(df$variables[X], "") %>% .[[1]]}) %>% reduce(c)

grades =  lapply(X=1:length(df$grades), FUN=function(X) {
  strsplit(df$grades[X], "") %>% .[[1]]}) %>% reduce(c)

participants =  lapply(X=1:length(df$participants), FUN=function(X) {
  rep(df$participants[X], nchar(df$variables[X])) })%>% reduce(c)

data.frame(participants, variables, grades)

然而,使用我的真实数据在我的机器上花费几分钟,我觉得它实际上效率不高,因为我需要3个不同的调用。

任何有效获取整洁数据的想法都会受到欢迎(我与tidyr / dplyr合作)

2 个答案:

答案 0 :(得分:3)

您可以使用strsplitunnest

library(tidyverse)
df %>% mutate_at(vars(variables,grades),~strsplit(.,"")) %>% unnest

#   participants variables grades
# 1            1         a      4
# 2            1         b      7
# 3            1         c      8
# 4            1         e      5
# 5            1         f      8
# 6            2         a      9
# 7            2         b      4
# 8            2         c      2

答案 1 :(得分:2)

data.table解决方案

setDT(df)
df[,lapply(.SD,function(x){strsplit(x,"") %>% unlist}),.SDcols=c("variables","grades"),by=participants]

结果:

   participants variables grades
1:            1         a      4
2:            1         b      7
3:            1         c      8
4:            1         e      5
5:            1         f      8
6:            2         a      9
7:            2         b      4
8:            2         c      2
>