Подмножество на условиях двух категориальных столбцов в r - PullRequest
3 голосов
/ 23 марта 2020

Я хотел бы установить значения из одного непрерывного столбца на основе условий двух категориальных столбцов.

> df.example <- data.frame(V1 = c("A", "A", "A", "B", "B", "B", "A", "A", "B", "B"),
+                V2 = c("B",  "A",  "B", "A", "B",  "A", "B",  "A", "B",  "A"),
+                     V3 = c("5",  "3",  "1", "7", "11", "2", "2", "11", "1", "3"))  
> df.example
   V1 V2 V3
1   A  B  5
2   A  A  3
3   A  B  1
4   B  A  7
5   B  B 11
6   B  A  2
7   A  B  2
8   A  A 11
9   B  B  1
10  B  A  3

Из df.example Я хотел бы получить те строки, где V3 является максимальным для каждой уникальной комбинации из V1 = V2; здесь

5   B  B 11
8   A  A 11

и минимум для каждой уникальной комбинации, когда V1 = / V2; здесь

3    A  B  1
10   B  A  3

Это, конечно, упрощено, в моих фреймах данных сотни категорий в V1 и V2.

Ответы [ 3 ]

2 голосов
/ 23 марта 2020

Вот подход data.table.

library(data.table)
setDT(df.example)
#In supplied data, V3 is a character vector
df.example[,V3 := as.numeric(as.matrix(V3))]
df.example[,lapply(.SD,function(x){
  if(V1==V2)
    {max(V3)}
  else
    {min(V3)}})
  ,by=list(V1,V2)]
   V1 V2 V3
1:  A  B  1
2:  A  A 11
3:  B  A  2
4:  B  B 11
1 голос
/ 23 марта 2020

Другой вариант:

library(dplyr)

df.example %>%
  group_by(V1, V2) %>%
  filter(V3 == eval(parse(text = paste0(c('max', 'min')[(V1 != V2) + 1], '(V3)'))))

Вывод:

# A tibble: 4 x 3
# Groups:   V1, V2 [4]
  V1    V2       V3
  <chr> <chr> <int>
1 A     B         1
2 B     B        11
3 B     A         2
4 A     A        11

Или аналогично @IanCampbell в dplyr:

library(dplyr)

df.example %>%
  group_by(V1, V2) %>%
  filter(if (V1 != V2) V3 == min(V3) else V3 == max(V3))

Просто добавьте mutate(V3 = as.integer(as.character(V3))) %>% в качестве второго шага, если ваш V3 действительно не integer.

0 голосов
/ 23 марта 2020

Одна возможность с использованием dplyr может быть:

df.example %>%
 filter(V1 == V2) %>%
 group_by(V1, V2) %>%
 summarise_all(max) %>%
 bind_rows(df.example %>%
            filter(V1 != V2) %>%
            group_by(V1, V2) %>%
            summarise_all(min))

  V1    V2       V3
  <fct> <fct> <dbl>
1 A     A        11
2 B     B        11
3 A     B         1
4 B     A         2
...