Select table 中的值以外部 table 为条件
Select values in a table conditional to an external table
我想 select 数据集中每个变量(列)的前 N 个值,其中 N 因列和行而异,并在另一个 table 中给出。下面是虹膜数据的示例:
data(iris)
head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
## Create a fake external table
ext.tab <- data.table(species=c("setosa","versicolor", "virginica" ),N1=c(1:3),N2=c(3:5),N3=c(5:7),N4=c(7:9))
head(ext.tab)
species N1 N2 N3 N4
1: setosa 1 3 5 7
2: versicolor 2 4 6 8
3: virginica 3 5 7 9
现在对于 Iris setosa,我想获得第 1 列('sepal.length' in iris)的第一个最大值(ext.tab 中的 N1数据),然后是第 2 列 (sepal.width) 的三个最大值 (ext.tab 中的 N2),然后是第 3 列 (petal.length) 的五个最大值 (N3),依此类推。然后移动到 Iris versicolor 并执行相同的操作。
结果可以是 table 或每个物种的列表,其中包含值本身或每个变量(列)的行索引。有什么快速实现方法的想法吗?
这是一个使用自定义函数的 tidyverse
方法。该函数将变量名和组名作为字符标量,将最大值的数量作为数字。函数内部是一个使用 .data
pronoun 的 dplyr
管道。然后,我将 ext.tab
重塑为长格式并按行应用 get_maximum()
。
library(tidyverse)
get_maximum <- \(.x, .group, .n_max, .dat) {
.dat %>%
filter(Species == .group) %>%
arrange(desc(.data[[.x]])) %>%
slice(seq_len(.n_max)) %>%
pull(.data[[.x]])
}
dat <- as_tibble(ext.tab) %>%
pivot_longer(-species) %>%
mutate(name = recode(
name,
N1 = "Sepal.Length",
N2 = "Sepal.Width",
N3 = "Petal.Length",
N4 = "Petal.Width"
)) %>%
rowwise() %>%
mutate(max_num = list(
get_maximum(name, species, value, iris)
)) %>%
ungroup()
如果您需要唯一的最大值,可以在自定义函数中添加distinct()
。
get_maximum_unique <- \(.x, .group, .n_max, .dat) {
.dat %>%
filter(Species == .group) %>%
distinct(.data[[.x]]) %>%
arrange(desc(.data[[.x]])) %>%
slice(seq_len(.n_max)) %>%
pull(.data[[.x]])
}
这是一个使用 data.table
的选项。我冒昧地重命名了列名。
cols <- setdiff(names(ext.tab), "Species")
iris[ext.tab, on=.(Species), by=.EACHI,
.(.(mapply(function(x, n) -head(sort(-x, partial=n), n),
x=mget(cols), n=mget(paste0("i.", cols)), SIMPLIFY=FALSE)))]$V1
数据:
library(data.table)
iris <- as.data.table(iris)
ext.tab <- data.table(Species=c("setosa", "versicolor", "virginica"),
Sepal.Length=c(1:3),
Sepal.Width=c(3:5),
Petal.Length=c(5:7),
Petal.Width=c(7:9))
输出:
[[1]]
[[1]]$Sepal.Length
[1] 5.8
[[1]]$Sepal.Width
[1] 4.4 4.2 4.1
[[1]]$Petal.Length
[1] 1.9 1.9 1.7 1.7 1.7
[[1]]$Petal.Width
[1] 0.4 0.4 0.6 0.4 0.5 0.4 0.4
[[2]]
[[2]]$Sepal.Length
[1] 7.0 6.9
[[2]]$Sepal.Width
[1] 3.4 3.3 3.2 3.2
[[2]]$Petal.Length
[1] 5.1 4.8 4.9 5.0 4.9 4.8
[[2]]$Petal.Width
[1] 1.7 1.6 1.6 1.8 1.5 1.5 1.6 1.5
[[3]]
[[3]]$Sepal.Length
[1] 7.7 7.9 7.7
[[3]]$Sepal.Width
[1] 3.8 3.8 3.6 3.4 3.4
[[3]]$Petal.Length
[1] 6.4 6.3 6.7 6.9 6.7 6.6 6.1
[[3]]$Petal.Width
[1] 2.5 2.5 2.4 2.5 2.4 2.4 2.3 2.3 2.3
简短说明:
- 执行左连接
iris[ext.tab, on=.(Species),
by=.EACHI
表示 ext.tab
的每一行
x=mget(cols)
获取 iris
中的列
mget(paste0("i.", cols))
获取每列需要的值的个数
-head(sort(-x, partial=n), n)
执行部分排序并提取前 n 个值
SIMPLIFY=FALSE
和 .(.( ))
只需要 return 结果作为列表
我想 select 数据集中每个变量(列)的前 N 个值,其中 N 因列和行而异,并在另一个 table 中给出。下面是虹膜数据的示例:
data(iris)
head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
## Create a fake external table
ext.tab <- data.table(species=c("setosa","versicolor", "virginica" ),N1=c(1:3),N2=c(3:5),N3=c(5:7),N4=c(7:9))
head(ext.tab)
species N1 N2 N3 N4
1: setosa 1 3 5 7
2: versicolor 2 4 6 8
3: virginica 3 5 7 9
现在对于 Iris setosa,我想获得第 1 列('sepal.length' in iris)的第一个最大值(ext.tab 中的 N1数据),然后是第 2 列 (sepal.width) 的三个最大值 (ext.tab 中的 N2),然后是第 3 列 (petal.length) 的五个最大值 (N3),依此类推。然后移动到 Iris versicolor 并执行相同的操作。
结果可以是 table 或每个物种的列表,其中包含值本身或每个变量(列)的行索引。有什么快速实现方法的想法吗?
这是一个使用自定义函数的 tidyverse
方法。该函数将变量名和组名作为字符标量,将最大值的数量作为数字。函数内部是一个使用 .data
pronoun 的 dplyr
管道。然后,我将 ext.tab
重塑为长格式并按行应用 get_maximum()
。
library(tidyverse)
get_maximum <- \(.x, .group, .n_max, .dat) {
.dat %>%
filter(Species == .group) %>%
arrange(desc(.data[[.x]])) %>%
slice(seq_len(.n_max)) %>%
pull(.data[[.x]])
}
dat <- as_tibble(ext.tab) %>%
pivot_longer(-species) %>%
mutate(name = recode(
name,
N1 = "Sepal.Length",
N2 = "Sepal.Width",
N3 = "Petal.Length",
N4 = "Petal.Width"
)) %>%
rowwise() %>%
mutate(max_num = list(
get_maximum(name, species, value, iris)
)) %>%
ungroup()
如果您需要唯一的最大值,可以在自定义函数中添加distinct()
。
get_maximum_unique <- \(.x, .group, .n_max, .dat) {
.dat %>%
filter(Species == .group) %>%
distinct(.data[[.x]]) %>%
arrange(desc(.data[[.x]])) %>%
slice(seq_len(.n_max)) %>%
pull(.data[[.x]])
}
这是一个使用 data.table
的选项。我冒昧地重命名了列名。
cols <- setdiff(names(ext.tab), "Species")
iris[ext.tab, on=.(Species), by=.EACHI,
.(.(mapply(function(x, n) -head(sort(-x, partial=n), n),
x=mget(cols), n=mget(paste0("i.", cols)), SIMPLIFY=FALSE)))]$V1
数据:
library(data.table)
iris <- as.data.table(iris)
ext.tab <- data.table(Species=c("setosa", "versicolor", "virginica"),
Sepal.Length=c(1:3),
Sepal.Width=c(3:5),
Petal.Length=c(5:7),
Petal.Width=c(7:9))
输出:
[[1]]
[[1]]$Sepal.Length
[1] 5.8
[[1]]$Sepal.Width
[1] 4.4 4.2 4.1
[[1]]$Petal.Length
[1] 1.9 1.9 1.7 1.7 1.7
[[1]]$Petal.Width
[1] 0.4 0.4 0.6 0.4 0.5 0.4 0.4
[[2]]
[[2]]$Sepal.Length
[1] 7.0 6.9
[[2]]$Sepal.Width
[1] 3.4 3.3 3.2 3.2
[[2]]$Petal.Length
[1] 5.1 4.8 4.9 5.0 4.9 4.8
[[2]]$Petal.Width
[1] 1.7 1.6 1.6 1.8 1.5 1.5 1.6 1.5
[[3]]
[[3]]$Sepal.Length
[1] 7.7 7.9 7.7
[[3]]$Sepal.Width
[1] 3.8 3.8 3.6 3.4 3.4
[[3]]$Petal.Length
[1] 6.4 6.3 6.7 6.9 6.7 6.6 6.1
[[3]]$Petal.Width
[1] 2.5 2.5 2.4 2.5 2.4 2.4 2.3 2.3 2.3
简短说明:
- 执行左连接
iris[ext.tab, on=.(Species),
by=.EACHI
表示ext.tab
的每一行
x=mget(cols)
获取iris
中的列
mget(paste0("i.", cols))
获取每列需要的值的个数-head(sort(-x, partial=n), n)
执行部分排序并提取前 n 个值SIMPLIFY=FALSE
和.(.( ))
只需要 return 结果作为列表