Представьте, что у меня есть таблица, подобная следующей.
set.seed(12)
table =
data.frame(
value = rnorm(n = 10),
par = runif (n = 10, min = - 1, max = 1)
)
Как я могу извлечь записи value
и par
, которые соответствуют двум наименьшим значениям par
выше нуля и двум самым большим значениям ниже нуля? Я хотел бы получить что-то вроде
out =
data.frame(
value = c(-0.2722960, -0.1064639, -0.3153487, 0.4280148),
par = c(-0.464112814, - 0.121141350, 0.009535904, 0.339638592)
)
Я был бы признателен, если бы это можно было сделать с помощью dplyr
, чтобы иметь возможность делать это для больших фреймов данных с группирующими переменными.
А как насчет фильтрации значений выше 0, сортировки значений и получения первых двух строк?
library(dplyr)
out <- table %>%
filter(par > 0) %>%
arrange(par) %>%
head(2) %>%
bind_rows(
table %>%
filter(par < 0) %>%
arrange(desc(par)) %>%
head(2)
)
> out
value par
1 -0.3153487 0.009535904
2 0.4280148 0.339638592
3 -0.1064639 -0.121141350
4 -0.2722960 -0.464112814
Если вы включите par >= 0
в свою группу, вы можете выбрать 2 минимальных абсолютных значения с помощью slice_min(abs(par), n = 2)
:
library(dplyr, warn.conflicts = FALSE)
set.seed(12)
table =
data.frame(
value = rnorm(n = 10),
par = runif (n = 10, min = - 1, max = 1)
)
table |>
group_by(pos = par >= 0) |>
slice_min(abs(par), n = 2) |>
ungroup()
#> # A tibble: 4 × 3
#> value par pos
#> <dbl> <dbl> <lgl>
#> 1 -0.106 -0.121 FALSE
#> 2 -0.272 -0.464 FALSE
#> 3 -0.315 0.00954 TRUE
#> 4 0.428 0.340 TRUE
Created on 2024-04-25 with reprex v2.1.0
Другая альтернатива:
# Toy data `my_table` at the end
aux <- my_table$par[my_table$par != 0] %>%
split(sign(.)) %>%
sapply(\(x) head(x[order(abs(x))], 2))
my_out <- my_table[my_table$par %in% aux, ]
rm(aux)
Ввод, вывод:
# Input
> arrange(my_table, par)
value par
1 -0.9567445 -0.804293921
2 -0.6282552 -0.622826146
3 -1.9976421 -0.564353914
4 -1.4805676 -0.563265665
5 -0.2722960 -0.464112814 #
6 -0.1064639 -0.121141350 #
7 9.0000000 0.000000000 # The presence of zero doesn't affect the output
8 -0.3153487 0.009535904 #
9 0.4280148 0.339638592 #
10 -0.9200052 0.419660932
11 1.5771695 0.575672695
# Output
> my_out
value par
1 -0.2722960 -0.464112814
2 -0.1064639 -0.121141350
3 -0.3153487 0.009535904
4 0.4280148 0.339638592
Данные игрушки:
my_table <- structure(list(
value = c(
-1.48056759491936, 1.57716947155863, -0.956744479084269, -0.920005247558641,
-1.99764209693134, -0.27229604424923, -0.315348711467784, -0.628255236517538,
-0.106463884872094, 0.428014802202354, 9),
par = c(
-0.56326566496864, 0.575672694947571, -0.804293920751661, 0.419660932384431,
-0.564353913534433, -0.464112814050168, 0.00953590357676148, -0.622826146427542,
-0.121141349896789, 0.339638591744006, 0)),
class = "data.frame", row.names = c(NA, -11L))
На всякий случай вам обязательно следует оценить свои шансы (и последствия) получить 0-значения для
par
, мне очень нравится, как Адриано решает эту проблему.