R在数据框中获取最小值选择2列上的行
R Get minimum value in dataframe selecting rows on 2 columns
我有一个类似于下面简化的数据框。我想首先 select 行基于 X 列具有相同的值,然后在那个 selection select 行基于 Y 列具有相同的值。然后从那个 selection,我想取最小值。我现在正在使用 forloop,但似乎必须有更简单的方法。谢谢!
set.seed(123)
data<-data.frame(X=rep(letters[1:3], each=8),Y=rep(c(1,2)),Z=sample(1:100, 12))
data
X Y Z
1 a 1 76
2 a 1 22
3 a 2 32
4 a 2 23
5 b 1 14
6 b 1 40
7 b 2 39
8 b 2 35
9 c 1 15
10 c 1 13
11 c 2 21
12 c 2 42
期望的结果:
X Y Z
2 a 1 22
4 a 2 23
5 b 1 14
8 b 2 35
10 c 1 13
11 c 2 21
这是一个data.table
解决方案:
library(data.table)
data = data.table(data)
data[, min(Z), by=c("X", "Y")]
根据 OP 的评论进行编辑:
如果我们排序的其中一列中有一个 NA 值,则会创建一个额外的行:
data[2,2] <-NA
data[, min(Z,na.rm = T), by=c("X", "Y")]
X Y V1
1: a 1 31
2: a NA 79
3: a 2 14
4: b 1 31
5: b 2 14
6: c 1 50
7: c 2 25
library(tidyverse)
data %>%
group_by(X, Y) %>%
summarise(Z = min(Z))
会成功的!现在的另一个答案是 data.table
方式,这是 tidyverse
。两者都是处理数据清理和操作的极其强大的方法 - 熟悉其中一种方法可能会有所帮助!
在 base 中,您可以使用 aggregate
从 Z
中获取最小值,按其余列分组,如:
aggregate(Z~.,data,min)
# X Y Z
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
如果组中有NA
:
data[2,2] <-NA
无视:
aggregate(Z~.,data,min)
# X Y Z
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
显示它:
aggregate(data$Z, list(X=data$X, Y=addNA(data$Y)), min)
# X Y x
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
#7 a <NA> 79
将这段代码分成多行可能会有所帮助,但它确实有效。在 Base-R
do.call(rbind,
lapply(unlist(lapply(split(data,data$X), function(x) split(x,x$Y)),recursive=F), function(y) y[y$Z==min(y$Z),])
)
X Y Z
a.1 a 1 31
a.2 a 2 14
b.1 b 1 31
b.2 b 2 14
c.1 c 1 50
c.2 c 2 25
我有一个类似于下面简化的数据框。我想首先 select 行基于 X 列具有相同的值,然后在那个 selection select 行基于 Y 列具有相同的值。然后从那个 selection,我想取最小值。我现在正在使用 forloop,但似乎必须有更简单的方法。谢谢!
set.seed(123)
data<-data.frame(X=rep(letters[1:3], each=8),Y=rep(c(1,2)),Z=sample(1:100, 12))
data
X Y Z
1 a 1 76
2 a 1 22
3 a 2 32
4 a 2 23
5 b 1 14
6 b 1 40
7 b 2 39
8 b 2 35
9 c 1 15
10 c 1 13
11 c 2 21
12 c 2 42
期望的结果:
X Y Z
2 a 1 22
4 a 2 23
5 b 1 14
8 b 2 35
10 c 1 13
11 c 2 21
这是一个data.table
解决方案:
library(data.table)
data = data.table(data)
data[, min(Z), by=c("X", "Y")]
根据 OP 的评论进行编辑:
如果我们排序的其中一列中有一个 NA 值,则会创建一个额外的行:
data[2,2] <-NA
data[, min(Z,na.rm = T), by=c("X", "Y")]
X Y V1
1: a 1 31
2: a NA 79
3: a 2 14
4: b 1 31
5: b 2 14
6: c 1 50
7: c 2 25
library(tidyverse)
data %>%
group_by(X, Y) %>%
summarise(Z = min(Z))
会成功的!现在的另一个答案是 data.table
方式,这是 tidyverse
。两者都是处理数据清理和操作的极其强大的方法 - 熟悉其中一种方法可能会有所帮助!
在 base 中,您可以使用 aggregate
从 Z
中获取最小值,按其余列分组,如:
aggregate(Z~.,data,min)
# X Y Z
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
如果组中有NA
:
data[2,2] <-NA
无视:
aggregate(Z~.,data,min)
# X Y Z
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
显示它:
aggregate(data$Z, list(X=data$X, Y=addNA(data$Y)), min)
# X Y x
#1 a 1 31
#2 b 1 31
#3 c 1 50
#4 a 2 14
#5 b 2 14
#6 c 2 25
#7 a <NA> 79
将这段代码分成多行可能会有所帮助,但它确实有效。在 Base-R
do.call(rbind,
lapply(unlist(lapply(split(data,data$X), function(x) split(x,x$Y)),recursive=F), function(y) y[y$Z==min(y$Z),])
)
X Y Z
a.1 a 1 31
a.2 a 2 14
b.1 b 1 31
b.2 b 2 14
c.1 c 1 50
c.2 c 2 25