【问题标题】:Create new column using group variables [duplicate]使用组变量创建新列[重复]
【发布时间】:2018-05-14 12:03:42
【问题描述】:

我正在尝试根据 R 中的分组变量生成一个新列。

我有一个测试结果数据框,其中每个学生的年终考试结果排成一行。

学生分为 A 组和 B 组。A 组在第一学期教化学,然后在第二学期教英语,B 组则反过来教。考试成绩都是年底的。

ID Group English Chemistry
1    A      9     4
2    B      7     3
3    B      7     6
4    A      3     10
etc

我想看看教学顺序是否会导致考试成绩的差异,所以我需要一个名为 Sem1 的列,其中包括 A 组的化学测试和 B 组的英语,另一个名为 Sem2 的列包括 A 组的英语和 B 组的英语化学。

所以它看起来像这样:

ID Group English Chemistry   Sem1  Sem2
1    A      9     4          4       9
2    B      7     3          3       7
3    B      7     6          6       6
4    A      3     10         10      3
etc

然后我可以根据学期进行统计。我怀疑这并不难,但我很简单。感谢所有帮助!

【问题讨论】:

  • 对于ID=3 为什么是Sem1=6Sem2=6English=7 怎么了?
  • 我可能没有正确理解您,但是您需要的信息不是已经存储在Group 列中了吗?可以运行时添加这些新列的目的是什么,例如t.test(English~Group)t.test(Chemistry~Group)
  • 感谢大家,感谢大家发现我的错误 Maurits。你说得很对。 Tifu 可能没有必要像你说的那样做,但我们只想一次比较所有第 1 学期的科目和第 2 学期的所有科目,这样我们就可以检验“学期顺序不会影响化学/英语的整体表现”的假设.

标签: r matrix grouping


【解决方案1】:

您可以使用ifelsemutate

require(tidyverse)

#Sample data
df <- data.frame(ID = c(1:4), 
                 Group = c("A", "B", "B", "A"), 
                 English = c(9, 7, 7, 3), 
                 Chemistry = c(4, 3, 6, 10))

df %>% 
  mutate(Sem1 = ifelse(Group == "A", Chemistry, English), 
         Sem2 = ifelse(Group == "A", English, Chemistry))

结果:

  ID Group English Chemistry Sem1 Sem2
1  1     A       9         4    4    9
2  2     B       7         3    7    3
3  3     B       7         6    7    6
4  4     A       3        10   10    3

编辑 - 建议 case_when 并为:ifelsecase_whentransform 做基准测试

使用相同的示例数据,您也可以使用dplyr::case_when()

df %>% 
        mutate(Sem1 = case_when(Group == "A" ~ Chemistry, 
                                Group == "B" ~ English),
               Sem2 = case_when(Group == "A" ~ English,
                                Group == "B" ~ Chemistry))

但是,包括@Maurits Evers 回答谁使用base R transform,我想知道哪个是最快的。

新样本数据

df <- data.frame(ID = c(1:100), 
                 Group = rep(sample(c("A", "B"), replace = TRUE), 100), 
                 English = rnorm(100, mean = 85, sd = 10), 
                 Chemistry = rnorm(100, mean = 85, sd = 10))

基准测试:

require(rbenchmark) 

benchmark("ifelse" = {df %>% 
    mutate(Sem1 = ifelse(Group == "A", Chemistry, English), 
           Sem2 = ifelse(Group == "A", English, Chemistry))
},
"case_when" = {
  df %>% 
    mutate(Sem1 = case_when(Group == "A" ~ Chemistry, 
                            Group == "B" ~ English),
           Sem2 = case_when(Group == "A" ~ English,
                            Group == "B" ~ Chemistry))
},
"transform" = {
  transform(
    df, 
    Sem1 = ifelse(Group == "A", Chemistry, English), 
    Sem2 = ifelse(Group == "A", English, Chemistry))
},
replications = 1000,
columns = c("test", "replications", "elapsed",
            "relative", "user.self", "sys.self")) 

结果:

       test replications elapsed relative user.self sys.self
2 case_when         1000    2.18    4.449      2.11     0.01
1     ifelse         1000    1.58    3.224      1.57     0.00
3 transform         1000    0.49    1.000      0.48     0.00

【讨论】:

  • 这很棒 - 转换功能对我来说似乎是最简单的并且运行良好。谢谢!
  • 不客气 :) 我认为我的转换(即@Maurits Evers)的主要问题是你不能通过管道(%>%)它。这可能会破坏流程。
【解决方案2】:

假设您在预期输出的第 3 行中出现错误,这里是使用 transform 的基本 R 解决方案:

transform(
    df, 
    Sem1 = ifelse(Group == "A", Chemistry, English), 
    Sem2 = ifelse(Group == "A", English, Chemistry))
#  ID Group English Chemistry Sem1 Sem2
#1  1     A       9         4    4    9
#2  2     B       7         3    7    3
#3  3     B       7         6    7    6
#4  4     A       3        10   10    3

样本数据

df <- read.table(text =
    "ID Group English Chemistry
1    A      9     4
2    B      7     3
3    B      7     6
4    A      3     10", header = T)

【讨论】:

  • 如上所述,这真的很有帮助 - 非常有用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多