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

R中的数据表解决方案,用于查找组最小值/最大值,r,data.table,R,Data.table,资料 我有'student'和'score'列,希望使用data.table创建'min'和'max',简单地说就是忽略NA值的每个学生的最小值和最大值。如果所有值均为NA,则只需将“NA”列为最小值/最大值。您可以使用函数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), "min"=c(6,6,6,1,1,1,3

资料


我有'student'和'score'列,希望使用data.table创建'min'和'max',简单地说就是忽略NA值的每个学生的最小值和最大值。如果所有值均为NA,则只需将“NA”列为最小值/最大值。

您可以使用函数
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),
                "min"=c(6,6,6,1,1,1,3,3,3),
                "max"=c(7,7,7,6,6,6,8,8,8))
结果:

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) })

函数
ave
将一个数值向量作为第一个参数,并且以下所有向量都是分组变量。FUN参数是您希望应用的函数。

您可以使用函数
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),
                "min"=c(6,6,6,1,1,1,3,3,3),
                "max"=c(7,7,7,6,6,6,8,8,8))
结果:

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) })

函数
ave
将一个数值向量作为第一个参数,并且以下所有向量都是分组变量。FUN参数是您希望应用的函数。

使用
数据。表

> 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(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

使用
数据表

> 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(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

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

library(dplyr)
data %>%
  group_by(student) %>%
  mutate(min =  min(score, na.rm = TRUE), max = max(score, na.rm = TRUE))
编辑:我不知道你为什么要这样做。将汇总统计数据与原始数据相结合是不好的做法。这会导致冗余/重复。当然,您只希望每个学生都有一个单独的结果:

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

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

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

library(dplyr)
data %>%
  group_by(student) %>%
  mutate(min =  min(score, na.rm = TRUE), max = max(score, na.rm = TRUE))
编辑:我不知道你为什么要这样做。将汇总统计数据与原始数据相结合是不好的做法。这会导致冗余/重复。当然,您只希望每个学生都有一个单独的结果:

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

另一个
数据表
选项:

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