【发布时间】:2021-10-25 19:06:58
【问题描述】:
我正在学习如何使用 R 进行聚合操作,但是我经常使用一种特定类型的操作,我希望在 R 或其附加组件中具有内置操作,或者至少是这样有比我想出的更好的实现。我不确定这是否有技术术语,但我称之为 MUSH 操作。在这里,您基本上将一个脏数据集与一堆随机位置的缺失数据混合成一个干净的数据集。有时我需要第一个非空值,有时是最后一个,有时是最后一个值,无论它是否为空。为简单起见,这是一个我只担心最后一个非空值的示例。
假设我有一个学生列表,其中包含他们的考试成绩、科目和负责考试的老师。数据输入人员有点粗心(纯属假设),并遗漏了一些老师的名字。此外,还有一些学生在最初进行考试时缺席,不得不在以后参加考试。
这是一个示例数据集:
STUDENTID SUBJECT TEACHER SCORE
1: 100 Art <NA> 96
2: 100 Art Smith NA
3: 100 Science Jones 75
4: 101 Art Smith NA
5: 101 Art Smith 50
6: 101 Science Jones 75
7: 102 Art <NA> 80
8: 102 Art Smith NA
这是设置数据框的代码:
# Setup data
a<-data.table(cbind(
"STUDENTID"=c("100","100","101","102")
,"SUBJECT"=c("Art","Science","Art","Art"))
,"TEACHER"=c("Smith","Jones","Smith","Smith")
,"SCORE"=c(NA,75,50,NA)
)
b<-data.table(
"STUDENTID"=c("100","101","101","102")
,"SUBJECT"=c("Art","Art","Science","Art")
,"TEACHER"=c(NA,"Smith","Jones",NA)
,"SCORE"=c(96,NA,75,80)
)
# Merge data
d <- merge(a, b, by = NULL, all = TRUE)
# Show output
d
我想通过合并基于 STUDENTID 和 SUBJECT 的所有行来清理此数据集。我想为其他每一行取第一个非空值。结果输出应如下所示:
STUDENTID SUBJECT TEACHER SCORE
1: 100 Art Smith 96
2: 100 Science Jones 75
3: 101 Art Smith 50
4: 101 Science Jones 75
5: 102 Art Smith 80
下面的代码完成了这个任务:
# dplyr to get last non null values
library(dplyr)
d <- d %>%
group_by(STUDENTID, SUBJECT) %>%
mutate(
bestTeacherRow = dplyr::last(na.omit(TEACHER)),
bestScoreRow = dplyr::last(na.omit(SCORE))
)
# Replace values with non-nulls
d$TEACHER <- d$bestTeacherRow
d$SCORE <- d$bestScoreRow
# Remove duplicates
d <- unique(d)
#Show output
d
有没有更优雅的方法来做到这一点?使用 dplyr 还是其他插件都没关系。
更重要的是,有没有办法在不指定每个标题/变量名称的情况下做到这一点?例如,如果在将来某个时间点将执行测试的 DATE 添加到数据集中,我可以运行相同的代码并获得相同的结果。我经常不得不从我的数据集中添加或删除变量,并且不得不返回并在整个数据转换过程中手动更改它们变得非常快。
【问题讨论】:
标签: r dplyr data.table aggregate