【问题标题】:Gathering/ melting multiple column sets, integer values for the variable column? [duplicate]收集/融合多个列集,变量列的整数值? [复制]
【发布时间】:2018-01-03 09:01:33
【问题描述】:

首先,我很抱歉,我知道我的问题与这里的其他几个问题重叠,但我对 R 真的很陌生,我找不到完全完成任务并且我实际上可以理解的答案。

我的数据集是这样的:

ID … Exam_t_minus_3 Exam_t_minus_2 Exam_t_minus_1 Grade_2012 Grade_2013 Grade_2014
1       Math        Physics         Chemestry         98         70         76
2       English     French          Russian           77         85         59
3       English     Chemistry       Biology           65         77         69

我希望它变成这样:

ID  …   i(as t_minus_i_)    Exam         Grade
1       3                   Math          98
1       2                   Physics       70
1       1                   Chemistry     76
2       3                   English       77
2       2                   French        85
2       1                   Russian       59

我已经完成了 swirl() 课程,并认为我可以使用 tidyr 来做到这一点,但我不知道如何收集多个列。我最终得到如下结果:

ID  …   ................    Exam         Grade
1       .                   Math          98
1       .                   Math          70
1       .                   Math          76
1       .                   Physics       98
1       .                   Physics       70
1       .                   Physics       76

我调查了这个:Gather multiple sets of columns 和其他一些人,但他们中的大多数人在中途失去了我。

我也尝试了这个问题的答案(我事先将收入列更改为以 T_minus_* 结尾):Gather multiple columns with tidyr

我试过了

library(data.table)
res = melt(setDT(sample_df), 
measure.vars = patterns("^Exam", "^Grade"), 
variable.name = "i")
res[, i := factor(i, labels = c("3","2", "1"))]

它完成了我需要的大部分工作,但是,我需要将 i 列中的值设为整数而不是分类变量,因为我需要它们用于未来的计算。

我试图做res$i <- as.numeric(res$i),但这改变了顺序,即“3”被评估为1,“1”被评估为3。 我试图把它排除在外,但这也给了我 1,2,3 以及 i 列值。

当我将收益列更改为 Earnings_T_minus_* 时,我是否可以以某种方式在 i 列中获得那些 * 值?

library(data.table)
res = melt(setDT(sample_df), 
measure.vars = patterns("^Exam_T_minus_*", "^Grade_T_minus_*"), 
variable.name = "i")

抱歉,这个问题有点长,可能有点混乱,但希望有人能指引我正确的方向。

【问题讨论】:

  • 为了解决我的问题,我只是使用 select() 来重新排列我的列,然后再融化。但是,它是合适的,因为我需要从 3 到 1 的数字。因此,我会留下我的问题,以防有人可以为我提供更好的解决方案。

标签: r tidyr melt


【解决方案1】:

使用dplyrtidyr 的解决方案。

需要两次gather进程。第一次,我们可以收集i(as t_minus_i_)Exam。第二次,我们可以收集YearGrade

starts_with 是一个辅助函数,可以选择以字符串开头的列。 sub 是将字符串替换为空字符串 "" 以进一步格式化列。 as.integer 是将字符数转换为整数。 dt2 是最终输出。

library(dplyr)
library(tidyr)

dt2 <- dt %>%
  # First gather process: gather the i(as t_minus_i_) and Exam
  gather(`i(as t_minus_i_)`, Exam, starts_with("Exam")) %>%
  mutate(`i(as t_minus_i_)` = as.integer(sub("Exam_t_minus_", "", `i(as t_minus_i_)`))) %>%
  # Second gather process: gather the Grade
  gather(Year, Grade, starts_with("Grade")) %>%
  mutate(Year = as.integer(sub("Grade_", "", Year))) %>%
  arrange(ID)

dt2
#    ID i(as t_minus_i_)      Exam Year Grade
# 1   1                3      Math 2012    98
# 2   1                2   Physics 2012    98
# 3   1                1 Chemestry 2012    98
# 4   1                3      Math 2013    70
# 5   1                2   Physics 2013    70
# 6   1                1 Chemestry 2013    70
# 7   1                3      Math 2014    76
# 8   1                2   Physics 2014    76
# 9   1                1 Chemestry 2014    76
# 10  2                3   English 2012    77
# 11  2                2    French 2012    77
# 12  2                1   Russian 2012    77
# 13  2                3   English 2013    85
# 14  2                2    French 2013    85
# 15  2                1   Russian 2013    85
# 16  2                3   English 2014    59
# 17  2                2    French 2014    59
# 18  2                1   Russian 2014    59
# 19  3                3   English 2012    65
# 20  3                2 Chemistry 2012    65
# 21  3                1   Biology 2012    65
# 22  3                3   English 2013    77
# 23  3                2 Chemistry 2013    77
# 24  3                1   Biology 2013    77
# 25  3                3   English 2014    69
# 26  3                2 Chemistry 2014    69
# 27  3                1   Biology 2014    69

数据

dt <- read.table(text = "ID Exam_t_minus_3 Exam_t_minus_2 Exam_t_minus_1 Grade_2012 Grade_2013 Grade_2014
1       Math        Physics         Chemestry         98         70         76
                 2       English     French          Russian           77         85         59
                 3       English     Chemistry       Biology           65         77         69",
                 header = TRUE, stringsAsFactors = FALSE)

【讨论】:

    【解决方案2】:

    您的data.table 方法几乎是正确的。用多列重塑是要走的路。

    library(data.table)
    melt(setDT(sample_df), 
         measure.vars = patterns("^Exam", "^Grade"), value.name = c("Exam", "Grade"), 
         variable.name = "i", variable.factor = FALSE)[
           , i := 4L - as.integer(i)][order(ID)]
    
       ID i      Exam Grade
    1:  1 3      Math    98
    2:  1 2   Physics    70
    3:  1 1 Chemistry    76
    4:  2 3   English    77
    5:  2 2    French    85
    6:  2 1   Russian    59
    7:  3 3   English    65
    8:  3 2 Chemistry    77
    9:  3 1   Biology    69
    

    唯一的修改是将variable.factor = FALSE作为参数传递给melt(),在强制转换为整数后对i进行一些算术运算,并将结果适当地传递给order()

    【讨论】:

      猜你喜欢
      • 2018-04-26
      • 2016-05-15
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 2022-11-03
      • 2018-09-24
      相关资源
      最近更新 更多