在R中查找组最小值/最大值的数据表解决方案



数据

data=data.frame("student"=c(1,1,1,2,2,2,3,3,3),
"score"=c(NA,7,6,6,1,4,8,NA,3),
"min"=c(6,6,6,1,1,1,3,3,3),
"max"=c(7,7,7,6,6,6,8,8,8))

我有"student"one_answers"score"列,希望使用数据。能够创建"min"one_answers"max",简单地说,这是每个学生忽略NA值的最小值和最大值。如果所有值都是NA,那么只需将"NA"列为最小值/最大值。

使用data.table

library(data.table)
setDT(data)
data[, c("min", "max"):= list(min(score, na.rm = TRUE), 
max(score,  na.rm = TRUE)), student]
data
#   student score min max
#1:       1    NA   6   7
#2:       1     7   6   7
#3:       1     6   6   7
#4:       2     6   1   6
#5:       2     1   1   6
#6:       2     4   1   6
#7:       3     8   3   8
#8:       3    NA   3   8
#9:       3     3   3   8

或使用dplyr

library(dplyr)
data %>%
group_by(student) %>%
mutate(min =  min(score, na.rm = TRUE), max = max(score, na.rm = TRUE))

但如果任何学生的所有分数都是NA,OP希望返回NA。此解决方案解决了Inf问题。

data=data.frame("student"=c(1,1,1,2,2,2,3,3,3),
"score"=c(NA,NA,NA,6,1,4,8,NA,3))
> dt <- data.table(data); dt
student score
1:       1    NA
2:       1    NA
3:       1    NA
4:       2     6
5:       2     1
6:       2     4
7:       3     8
8:       3    NA
9:       3     3

创建一个函数来处理所有值都为NA的情况,以返回NA

min.na = function(x) if (all(is.na(x))) x[NA_integer_] else min(x, na.rm = TRUE)
max.na = function(x) if (all(is.na(x))) x[NA_integer_] else max(x, na.rm = TRUE)
dt[, c("min", "max") := list(min.na(score), max.na(score)), by=student]
dt
student score min max
1:       1    NA  NA  NA
2:       1    NA  NA  NA
3:       1    NA  NA  NA
4:       2     6   1   6
5:       2     1   1   6
6:       2     4   1   6
7:       3     8   3   8
8:       3    NA   3   8
9:       3     3   3   8

编辑:我不知道你为什么要这么做。将汇总统计数据与原始数据相结合是不好的做法。它会导致冗余/重复。当然,你只想给每个学生一个单独的结果:

dt[, .(min=min.na(score), max=max.na(score)), by=student]
student min max
1:       1  NA  NA
2:       2   1   6
3:       3   3   8

我知道最后一部分不是要求的,但我总是检查他们的要求是否是他们真正想要的。(

另一个data.table选项:

setDT(data)[, c("min","max") := as.list(range(score, na.rm=TRUE)), student]

您可以使用函数ave:来完成此操作

data=data.frame("student"=c(1,1,1,2,2,2,3,3,3),
"score"=c(NA,7,6,6,1,4,8,NA,3))
data$min = ave(data$score, data$student, FUN = function(x){ min(x, na.rm = T) })
data$max = ave(data$score, data$student, FUN = function(x){ max(x, na.rm = T) })

结果:

> data
student score min max
1       1    NA   6   7
2       1     7   6   7
3       1     6   6   7
4       2     6   1   6
5       2     1   1   6
6       2     4   1   6
7       3     8   3   8
8       3    NA   3   8
9       3     3   3   8

函数ave将一个数字向量作为第一个参数,随后的所有向量都是分组变量。FUN参数是您希望应用的函数。

最新更新