#r #dplyr
#r #dplyr
Вопрос:
У меня есть набор данных, который выглядит как:
Group Gene Score direct_count secondary_count SD_per_group
1 AQP11 0.31 4 5 0.12
1 CLNS1A 0.27 0 2 0.12
1 RSF1 0.49 3 6 0.12
2 CFDP1 0.58 1 2 0.02
2 CHST6 0.59 1 3 0.02
2 UBL 0.56 1 3 0.02
3 ACE 0.634 1 1 0.001
3 NOS2 0.6345 1 1 0.001
4 Gene1 0.1 10 20 0.45
4 Gene2 0.68 3 1 0.45
4 Gene3 0.7 0 1 0.45
5 AGT 0.75 0 0 0.00
Я выбираю определенные гены для каждой группы на основе их Score
по отношению к SD_per_group
последующим их direct_count
, и secondary_count
если на каждом шаге фильтрации выбирается более 1 гена.
Я пытаюсь выбрать ген для каждой группы на первом этапе фильтрации, если наивысший балл> SD_per_group
оценка по сравнению с другими в группе (затем, если выбрано более 1 гена, я выбираю гены на основе count
столбцов, сохраняя только несколько генов на группу, если они также имеют совпадающие столбцы прямого и вторичного подсчета).
Я кодирую это с помощью:
new_df <- df %>%
group_by(Group) %>%
filter((max(Score) - Score)<SD_per_group) %>%
slice_max(direct_count, n = 1) %>%
slice_max(secondary_count, n = 1) %>%
ungroup()
Однако, в случае, когда в группе для начала есть только 1 ген, а SD_per_group равен 0.00, этот единственный ген не выбирается для этой группы, но мне это нужно.
Как я могу использовать filter((max(Score) - Score)<SD_Per_Group)
с учетом групп, имеющих только 1 ген для начала? В приведенных в моем примере данных мой код ничего не выбирает для группы 5.
Входные данные:
structure(list(Group = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 4L,
4L, 4L, 5L), Gene = c("AQP11", "CLNS1A", "RSF1", "CFDP1", "CHST6",
"UBL", "ACE", "NOS2", "Gene1", "Gene2", "Gene3", "AGT"), Score = c(0.31,
0.27, 0.49, 0.58, 0.59, 0.56, 0.634, 0.6345, 0.1, 0.68, 0.7,
0.75), direct_count = c(4L, 0L, 3L, 1L, 1L, 1L, 1L, 1L, 10L,
3L, 0L, 0L), secondary_count = c(5L, 2L, 6L, 2L, 3L, 3L, 1L,
1L, 20L, 1L, 1L, 0L), SD_per_group = c(0.12, 0.12, 0.12, 0.02,
0.02, 0.02, 0.001, 0.001, 0.45, 0.45, 0.45, 0)), row.names = c(NA,
-12L), class = c("data.table", "data.frame"))
Ожидаемый результат:
Group Gene Score direct_count secondary_count SD_per_group
1 RSF1 0.4900 3 6 0.120 #highest score >SD_per_group
2 CHST6 0.5900 1 3 0.020 #highest secondary count
3 ACE 0.6340 1 1 0.001 #ACE and NOS2 <SD diff and matching both counts
3 NOS2 0.6345 1 1 0.001
4 Gene2 0.6800 3 1 0.450 #highest direct count
5 AGT 0.75 0 0 0.00 #only gene in the group so must be selected
Ответ №1:
Вы можете включить оба параметра фильтрации, используя if else .
df %>% group_by(Group) %>% filter(if(n() > 1) {(max(Score) - Score) < SD_per_group} else TRUE) %>%
slice_max(direct_count, n = 1) %>%
slice_max(secondary_count, n = 1) %>%
ungroup()
# A tibble: 6 x 6
Group Gene Score direct_count secondary_count SD_per_group
<int> <chr> <dbl> <int> <int> <dbl>
1 1 RSF1 0.49 3 6 0.12
2 2 CHST6 0.59 1 3 0.02
3 3 ACE 0.634 1 1 0.001
4 3 NOS2 0.634 1 1 0.001
5 4 Gene2 0.68 3 1 0.45
6 5 AGT 0.75 0 0 0
>
Ответ №2:
Если я правильно понимаю вашу необходимую логику, вы хотите сохранить любые строки, в которых для этой группы есть только 1 строка?
Если это так, вы можете добавить or
оператор в свой фильтр, чтобы также сохранить любые строки, в которых есть только количество 1 (т. Е. n() == 1
) Для приведенного ниже:
код
new_df <- df %>%
group_by(Group) %>%
filter((max(Score) - Score)<SD_per_group | n() == 1) %>%
slice_max(direct_count, n = 1) %>%
slice_max(secondary_count, n = 1) %>%
ungroup()
ВЫВОД
> new_df
# A tibble: 6 x 6
Group Gene Score direct_count secondary_count SD_per_group
<int> <chr> <dbl> <int> <int> <dbl>
1 1 RSF1 0.49 3 6 0.12
2 2 CHST6 0.59 1 3 0.02
3 3 ACE 0.634 1 1 0.001
4 3 NOS2 0.634 1 1 0.001
5 4 Gene2 0.68 3 1 0.45
6 5 AGT 0.75 0 0 0