2013-08-06 2 views
1

У меня есть набор данных, который содержит данные о питании 3 животных, состоящие из идентификаторов тегов животных (1,2,3), типа (A, B) и количества (кг) корма данного в каждом «еды»:R суммарная сумма данных, которые удовлетворяют уникальным условиям

Animal FeedType Amount(kg) 
Animal1  A   10 
Animal2  B   7 
Animal3  A   4 
Animal2  A   2 
Animal1  B   5 
Animal2  B   6 
Animal3  A   2 

Используя это, я хочу, чтобы иметь возможность выводить матрицу, ниже которой имеет unique('Animal') как ее строк, unique('FeedType') в качестве столбцов и кумулятивный поток Количество (кг) в соответствующих ячейках матрицы.

  A B 
Animal1 10 5 
Animal2 2 13 
Animal3 6 0 

Я начал программировать решение, используя два для петель, как показано ниже:

dataframe = read_delim(input_url, header=TRUE, sep = ";") 
animal_feed_matrix = matrix(0,nrow(unique('Animal')),nrow(unique('FeedType'))) 
for (i in 1:length(unique('Animal'))){ 
a= unique('Animal')[i] 
    for (j in 1:length(unique('FeedType'))){ 
    ft= unique('FeedType')[j] 
    animal_feed_matrix[i,j] = sum(dataframe [(dataframe ['Animal']==a & dataframe ['FeedType']==ft),'Amount(kg)']) 
    } 
} 

Но я знаю, что это очень неэффективный способ решения проблемы, (плюс код выше должен быть завершено для работы). Я знаю, что R имеет уровней и Факторы, которые я чувствую, могут решить проблему более элегантно.

P.S:This question несколько похож на мой, но даже если решение моей проблемы содержится внутри, оно ускользает от меня.

ответ

1

В базовой R:

out <- with(mydf, tapply(Amount, list(Animal, FeedType), sum)) 

     A B 
Animal1 10 5 
Animal2 2 13 
Animal3 6 NA 

Затем, чтобы изменить NA к 0 (как в вашем примере), просто сделать:

out[is.na(out)] <- 0 
+0

Ничего себе, это достаточно мощно для одной строки кода. Работает как шарм! Просто краткий вопрос: матрица «out» слишком скудна сейчас, потому что у меня слишком много столбцов FeedType. Как я могу опустить те типы FeedTypes, которые происходят меньше чем определенное число раз? (например, я хочу исключить столбец FeedTypeA в 'out' если в 'mydf' это произошло только один раз) – Rhubarb

+0

@Berkan Я бы, вероятно, предварительно обработал исходный фрейм данных, за исключением FeedTypes ниже определенного порога, прежде чем вы запустите 'by'. Но вы можете просто удалить столбцы из полученной матрицы с чем-то вроде: 'out [,! Colnames (out) ==" A ", drop = FALSE]' ('drop = FALSE' не требуется в больших матрицах, но предотвращает принуждение матрицы-примера с двумя столбцами к вектору). – Thomas

1

Вы можете сделать это с помощью функции dcast() из библиотеки reshape2.

library(reshape2)  
dcast(df,Animal~FeedType,sum,value.var="Amount") 
    Animal A B 
1 Animal1 10 5 
2 Animal2 2 13 
3 Animal3 6 0 
+0

Спасибо, но код выдает ошибку : [Использование столбца подсектора как значения: используйте значение.var для переопределения. Ошибка в vaggregate (.value = значение, .group = в целом, .fun = fun.aggregate,: не удалось найти функцию ".fun]. Также в этом однострочном файле, где я указываю, что сумма на сумму? – Rhubarb

+0

Функция dcast() автоматически использует третий столбец (если есть только три) для вычисления суммы. Обновленный пример для более общего решения с аргументом value.var = (чтобы показать, какой столбец использовать). Для вашей ошибки - кажется, что в вашей сессии сумма используется как некоторая переменная. См. этот вопрос [SO] (http://stackoverflow.com/questions/7082792/error-message-running-the-example-from-the-reshape2-help -page) –

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