动态归一化所有组内第一个元素为1的行

3
假设我有以下数据框:
      year subject grade study_time
1    1       a    30         20
2    2       a    60         60
3    1       b    30         10
4    2       b    90        100

我希望能够按科目将成绩和学习时间除以它们在每个科目中的第一条记录。我进行如下操作:
df %>% 
  group_by(subject) %>%
  mutate(RN = row_number()) %>% 
  mutate(study_time = study_time/study_time[RN ==1], 
          grade = grade/grade[RN==1]) %>%
 select(-RN)

我会得到以下输出。
      year subject grade study_time
1    1       a    1         1
2    2       a    2         3
3    1       b    1         1
4    2       b    3        10

当我知道变量名时,这个任务相对容易。但是,我正在尝试编写一个通用函数,该函数能够作用于任何数据框/数据表/ Tibble,其中我可能不知道需要改变的变量名,我只知道不需要改变的变量名。我正在尝试使用tidyverse/data.table完成此操作,但是我无法让任何内容正常工作。
非常感谢您的帮助。
1个回答

2
我们按“主题”分组,并使用mutate_at将多个列更改为将元素除以first元素。
library(dplyr)
df %>%
   group_by(subject) %>%
   mutate_at(3:4, funs(./first(.)))
# A tibble: 4 x 4
# Groups:   subject [2]
#   year subject grade study_time
#  <int> <chr>   <dbl>      <dbl>
#1     1 a           1          1
#2     2 a           2          3
#3     1 b           1          1
#4     2 b           3         10

1
哦,哇。这比我想象的要简单得多,而且非常简洁明了。它完美地运作了,非常感谢你的帮助! :) - Cameron Fincher
在回答中加入有关mutate_at函数的更多背景信息以及它与普通mutate的区别可能会对未来的观众有所帮助。 - IRTFM
有没有一种方法可以在data.table中完成上述操作?我喜欢dplyr的可读性,但想要data.table的速度。 - Cameron Fincher
@CameronFincher 确定 setDT(df)[, (3:4) := lapply(.SD, function(x) x/x[1]), subject, .SDcols = 3:4] - akrun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接