2016-03-30 2 views
2

У меня есть кадр данных, ДФ:.Как encorporate петли в моих Подменят данные

ID <- c('ID1','ID2','ID3','ID4','ID5','ID6','ID7','ID8','ID9','ID10','ID11') 
hr <- c(56,32,38,NA,42,23,35,23,25,44,32) 
cr <- c(10,20,10,10,10,20,20,30,40,30,40) 
desc <- c("yellow","blue","green","yellow","green","green","blue","yellow","blue","green","blue") 
df <- data.frame(ID,hr,cr,desc) 

Я хочу, чтобы выделить каждое уникальное значение DF $ CR в новое подмножество (т.е. группы всех строки, где кр = 10 или cr = 20 и т. Д.). Затем я хочу заказать каждое подмножество и сохранить первое уникальное значение каждого описания цвета (т. Е. Если желтый цвет появляется четыре раза в столбце df $ desc, я хочу сохранить строку только с наименьшим значением df $ hr).

Я делал это в коде:

cr10=subset(df,(df$cr==10)) 
cr10=cr10[order(cr10$hr) , ] 
cr10=subset(cr10,!duplicated(desc)) 

cr20=subset(df,(df$cr==20)) 
cr20=cr20[order(cr20$hr) , ] 
cr20=subset(cr20,!duplicated(desc)) 

cr30=subset(df,(df$cr==30)) 
cr30=cr30[order(cr30$hr) , ] 
cr30=subset(cr30,!duplicated(desc)) 

cr40=subset(df,(df$cr==40)) 
cr40=cr40[order(cr40$hr) , ] 
cr40=subset(cr40,!duplicated(desc)) 

df_new=rbind(cr10,cr20,cr30,cr40) 
> df_new 
    ID hr cr desc 
3 ID3 38 10 green 
1 ID1 56 10 yellow 
6 ID6 23 20 green 
2 ID2 32 20 blue 
8 ID8 23 30 yellow 
10 ID10 44 30 green 
9 ID9 25 40 blue 

Однако это очень длительный. Есть ли способ сократить код или включить петлю, чтобы, если бы у меня было значение тысяч cr, мне не нужно было бы вводить выше 1000 раз?

ответ

4

Вы можете сделать это с dplyr и: df %>% group_by(cr, desc) %>% arrange(hr) %>% slice(1) %>% ungroup()

> df %>% group_by(cr, desc) %>% arrange(hr) %>% slice(1) %>% ungroup() 
Source: local data frame [7 x 4] 

ID hr cr desc 
(fctr) (dbl) (dbl) (fctr) 
1 ID3 38 10 green 
2 ID1 56 10 yellow 
3 ID2 32 20 blue 
4 ID6 23 20 green 
5 ID10 44 30 green 
6 ID8 23 30 yellow 
7 ID9 25 40 blue 
1

dplyr ваш друг здесь

library(dplyr) 
df %>% group_by(cr, desc) %>% arrange(hr) %>% 
mutate(dup = duplicated(desc, cr)) %>% filter(dup == FALSE) %>% select(-dup) 
+1

Oww, теперь не о функции среза (1), ответ Винсента явно лучше! – Edwin

4

Использование data.table Я хотел бы использовать это unique метод после того, как быстро сортировки набора данных. Это позволит избежать любой групповыми операциями и будет использовать полностью оптимизированные forder и unique.data.table функции

library(data.table) 
unique(setDT(df)[order(cr, hr)], by = c("cr", "desc")) 
#  ID hr cr desc 
# 1: ID3 38 10 green 
# 2: ID1 56 10 yellow 
# 3: ID6 23 20 green 
# 4: ID2 32 20 blue 
# 5: ID8 23 30 yellow 
# 6: ID10 44 30 green 
# 7: ID9 25 40 blue 

Или data.table эквивалент предлагаемого dplyr раствора может быть (как уже упоминалось) @Arun

setDT(df)[order(hr), .SD[1L], keyby = .(cr, desc)] 

Или аналогичным образом, используя базу R, вы можете сделать

res <- df[with(df, order(cr, hr)), ] 
res[!duplicated(res[c("cr", "desc")]), ] 
#  ID hr cr desc 
# 3 ID3 38 10 green 
# 1 ID1 56 10 yellow 
# 6 ID6 23 20 green 
# 2 ID2 32 20 blue 
# 8 ID8 23 30 yellow 
# 10 ID10 44 30 green 
# 9 ID9 25 40 blue 
+1

Я думаю, что в этом случае 'setDT (df) [order (cr, hr), .SD [1L], by =. (Cr, desc)]' лучше, поскольку 'unique()' должен получить весь сначала данные (переупорядочиваются) ... тогда как при использовании '.SD [1L]' только индексы вычисляются в 'i'. – Arun

+1

@Arun это была моя первоначальная мысль, но тогда я полагал, что 'unique' намного более оптимизирован, чем' .SD [1L] 'в сочетании с' by' (по крайней мере, в стабильной версии). Возможно, я добавлю бенчмарк, когда у меня будет время. –

+2

Оба одинаково оптимизированы. Но здесь важна не оптимизация, а ненужная копия. Глубокие (ненужные) копии могут сорвать любое количество оптимизаций, которые мы делаем. :-P. Также я лично считаю код '.SD [1L]' более удобным для чтения (там я сказал это: -P). Как правило, я откладываю функции DT, если требование op такое же, как * точное * использование, которое оно было разработано для ... Else, я перехожу к '[.data.table'. – Arun

Смежные вопросы