2012-04-27 9 views
2

Я пытаюсь изменить/уменьшить свои данные. До сих пор я использую цикл for (очень медленный), но из того, что я воспринимаю, это должно быть довольно быстро с Plyr.Подмножество данных по условию

У меня есть много групп (фирм, как фактор в наборе данных), и я хочу полностью отказаться от каждой фирмы, которая показывает 0 записей для value в любой из этих фирм. Таким образом, я создаю новый data.frame, но в некоторых случаях все группы покажут 0 для value.

for петля:

Data Creation: 

set.seed(1) 
mydf <- data.frame(firmname = sample(LETTERS[1:5], 40, replace = TRUE), 
     value = rpois(40, 2)) 

----------------------------- 
splitby = mydf$firmname 


new.data <- data.frame() 

for (i in 1:(length(unique(splitby)))) { 
temp <- subset(mydf, splitby == as.character(paste(unique(splitby)[i]))) 
    if (all(temp$value > 0) == "TRUE") {  
    new.data <- rbind(new.data, temp) 
} 
} 

Delete all empty firm factors 
new.data$splitby <- factor(new.data$splitby) 

Есть ли способ добиться того, что с plyr пакета? Можно ли использовать в этом контексте функцию subset?

EDIT: В целях воспроизведения проблемы добавлено создание данных, как предлагается BenBarnes. Бен, спасибо за это. Кроме того, мой код изменен, чтобы соответствовать приведенным ниже ответам.

+0

Вы не предоставляют образцы данных, но это звучит как стандартное подмножество с помощью '[' operator. – Andrie

+0

@ Аndrie это звучит для меня, как будто он хочет отбросить все записи в группе, в которой любая запись соответствует некоторому условию. Так что 'plyr' или' by' кажутся проще. Ян, пожалуйста, прочитайте это, так как это поможет нам решить ваш вопрос: http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example –

+0

Большое спасибо за ваши ответы! Я отредактировал сообщение и добавил воспроизведение данных, как это предложил Бен (см. Ниже). – Jan

ответ

5

Вы могли бы поставить анонимную функцию в .fun аргумента в ddply():

set.seed(1) 

mydf <- data.frame(firmname = sample(LETTERS[1:5], 40, replace = TRUE), 
    value = rpois(40, 2)) 

library(plyr) 

ddply(mydf,.(firmname), function(x) if(any(x$value==0)) NULL else x) 

Или с помощью [, как это было предложено Andrie:

firms0 <- unique(mydf$firmname[which(mydf$value == 0)]) 

mydf[-which(mydf$firmname %in% firms0), ] 

Следует отметить, что результаты ddply сортируют по до firmname

EDIT

Для примера в комментариях, этот подход снова быстрее, чем при использовании ddply() для подмножества, выбирая только фирмы, имеющие более трех записей:

firmTable <- table(mydf$firmname) 

firmsGT3 <- names(firmTable)[firmTable > 3] 

mydf[mydf$firmname %in% firmsGT3, ] 
+0

Привет, Бен, спасибо за эти замечательные ответы! Это именно то, что я искал. Я не знал, как применить вторую версию ([операция) для целых групп. Как написано в комментарии выше, операция [[] работает намного быстрее, чем цикл Plyr или for. – Jan

+0

2-й ответ хорошо работает при настройке на значения одной ячейки. Будет ли он работать и при настройке на количество строк? Я попробовал Plyr: 'mydf <- ddply (mydf,. (Firmname), function (x) if (length (x $ firmname <3)) NULL else x)' и многие другие подходы с помощью '[' approach but can ' t заставить его работать. – Jan

+0

Я заработал! 'ddply (mydf,. (firmname), function (x) if (length (x $ firmname)> 3) NULL else x)' выполняет задание. Это выбирает все группы (фирмы) с более чем 3 наблюдениями. С '<' эти данные отсортированы. Наверное, это было только одно!). – Jan