Как извлечь уникальный элемент в соответствии с набором предпочтительных условий

Взяв кадр данных df, я хотел бы извлечь уникальное значение в соответствии со следующими предпочтительными условиями для каждого поля:

1- если C1 существует, извлечь соответствующее значение и игнорировать остальные

2- если C2 существует, извлеките соответствующее значение и игнорируйте остальные

... и так далее до C5

данные:

df <- data.frame (Field=rep(c("F1","F2","F3","F4","F5"),each=3),
              Cond=rep(c("C1","C2","C3","C4","C5"),3),
              Value=c(1:15))

желаемый вывод:

output <-  data.frame (F= c("F1","F2","F3","F4","F5"),
                   C= c("C1","C1","C2","C1","C3"),
                   Value= c(1,6,7,11,13))

(примечание 1: значения были установлены как таковые только для примера, реальные значения данных не упорядочены)

(примечание 2: столбец настоящее условие вообще не упорядочен в алфавитном порядке. Хотя я должен был иметь что-то вроде, если A существует, чем выбрать «значение A», в противном случае перейти к следующему условию «если B существует. .." и так далее)


person Rui    schedule 29.01.2017    source источник
comment
Можно ли предположить, что значения в C отсортированы?   -  person Roman Luštrik    schedule 30.01.2017
comment
@Roman, нет ... значения были установлены как таковые только для примера   -  person Rui    schedule 30.01.2017


Ответы (2)


Другой вариант — использовать data.table

library(data.table)
setDT(df)[order(Field, Cond), head(.SD, 1), by = Field]
#    Field Cond Value
#1:    F1   C1     1
#2:    F2   C1     6
#3:    F3   C2     7
#4:    F4   C1    11
#5:    F5   C3    13
person akrun    schedule 30.01.2017
comment
да, это действительно работает, если Cond нужно отсортировать по алфавиту. однако, если столбец сортировки не отсортирован в алфавитном порядке, этот пример не будет работать. - person Rui; 30.01.2017
comment
@Rui В этом случае преобразуйте его в factor и укажите levels в нужном вам порядке order(Field, factor(Cond, levels = lvl)) - person akrun; 30.01.2017

Если вы можете отсортировать data.frame перед обработкой, это довольно просто. Обратите внимание, что это работает для этого конкретного случая. Если ваши значения Cond изменятся, сортировка по алфавиту может выйти из строя.

library(dplyr)
df <- data.frame (Field=rep(c("F1","F2","F3","F4","F5"),each=3),
                  Cond=rep(c("C1","C2","C3","C4","C5"),3),
                  Value=c(1:15))

df <- df[with(df, order(Field, Cond)), ]
res <- df %>%
  group_by(Field) %>%
  filter(row_number() == 1)

Source: local data frame [5 x 3]
Groups: Field [5]

   Field   Cond Value
  <fctr> <fctr> <int>
1     F1     C1     1
2     F2     C1     6
3     F3     C2     7
4     F4     C1    11
5     F5     C3    13

Вот еще один, более общий способ сделать это. Порядок сортировки определен в so (см. этот вопрос). Обратите внимание, как я исказил значения для Cond, чтобы показать, что они не отсортированы по алфавиту.

df <- data.frame (Field=rep(c("F1","F2","F3","F4","F5"),each=3),
                  Cond=rep(c("rg1","kl2","xy3","rq4","ab5"),3),
                  Value=c(1:15))

so <- c("rg1","kl2","xy3","rq4","ab5")

df %>%
  group_by(Field) %>%
  slice(match(so, Cond)) %>%
  filter(row_number() == 1)

   Field   Cond Value
  <fctr> <fctr> <int>
1     F1    rg1     1
2     F2    rg1     6
3     F3    kl2     7
4     F4    rg1    11
5     F5    xy3    13
person Roman Luštrik    schedule 29.01.2017
comment
действительно, вы правы, я не думаю, что это будет проблемой. Мой условный столбец вообще не упорядочен по алфавиту. хотя я должен был иметь что-то вроде, если A существует, чем выбрать значение A, в противном случае перейти к следующему условию, если B существует... и так далее - person Rui; 30.01.2017
comment
@Rui Я изменил свой ответ и думаю, что теперь он должен работать для вашего общего случая. - person Roman Luštrik; 30.01.2017