Как извлечь уникальный элемент в соответствии с набором предпочтительных условий
Взяв кадр данных 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 существует, чем выбрал "значение", в противном случае переход к следующему условию "если B существует..." и т. д.)
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
Если вы можете отсортировать 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