Работа с выводом tapply () и ddply {plyr} в R: подмножества неравной длины - PullRequest
3 голосов
/ 02 ноября 2011

У меня есть фрейм данных:

> df <- data.frame(
+   Species = rep(LETTERS[1:4], times=c(5,6,7,6)),
+   Length = rep(11:14, each=3) 
+ )
> 
> df

Мне нужно иметь возможность подсчитать количество особей определенной длины для каждого вида (т. Е. Сколько особей в Виде Aимеют длину 1, 2, 3 и т. д.?) Затем мне нужно выполнить серию дополнительных анализов на выходе.Например, мне нужно рассчитать плотность особей каждой длины и уменьшение плотности от одного класса длины к следующему.

Это легко, если я сначала подмножеству данных:

Spec.A<-df[df$Species=="A",] 

#count number of specimens of each length; 
count<-table(Spec.A$Length)
count

#calculate density per length category (divide by total area sampled =30) 
density<-count/(30)
density

#calculate the decrease in density (delta.N) from one length category to the next; 
delta.N<-diff(density, lag=1, differences=1)
delta.N

Проблема заключается в том, что мне нужно выполнить эти вычисления для каждого вида (т. Е. Выполнить цикл по каждому подмножеству).

С одной стороны, я мог бы использовать tapply () с функцией, которая использует table ();

#function: count number of specimens of each length; 
count<-function(x){
table(x)
}

Number<-tapply(df$Length, df$Species, FUN=count, simplify=FALSE)
Number

Это дает мне то, что я хочу, но формат выводафанк, и я не могу понять, как выполнить дополнительный анализ результатов.

Я пытался использовать ddply () из plyr, что-то вроде:

ddply(df$Length, df$Species,
count)

Но я явно ненеправильно, и я даже не уверен, что ddply () подходит для моей проблемы, учитывая, что у меня разное количество наблюдений длины для каждого вида.

Должен ли я присматриваться к другимварианты в плир?Или есть способ написать цикл для , чтобы сделать то, что мне нужно?

Ответы [ 2 ]

3 голосов
/ 03 ноября 2011

Вы можете сделать это проще, используя функцию count в plyr

df1 <- ddply(df, .(Species, Length), count)
df2 <- ddply(df1, .(Species), mutate, Dens = freq/30, Del = diff(c(NA, Dens)))
3 голосов
/ 02 ноября 2011

Вы на правильном пути! tapply со списком вывода определенно один из способов, и может быть хорошим выбором, так как ваши выходы будут иметь различную длину.

ddply, как вы уже догадались, это другой способ. Ключевым моментом является то, что выходные данные функции, которую вы даете ddply, должны представлять собой фрейм данных со всей вашей статистикой в ​​«длинном» режиме (чтобы они правильно складывались). Простая функция count не может этого сделать, поэтому вам нужно создать свою собственную функцию. То, как я разрабатываю функцию для вызова ddply, на самом деле очень похоже на то, что вы делали: я получаю подмножество данных, а затем создаю свою функцию, используя это. Затем, когда вы отправите его в ddply, он будет применять эту функцию ко всем подмножествам.

SpeciesStats <- function(df) {
  counts    = table(df$Length)
  densities = counts/30
  delta.N   = diff(densities, lag=1, differences=1)

  data.frame(Length   = names(counts),
             Count    = as.numeric(counts),
             Density  = as.numeric(densities),
             delta.N  = c(NA, delta.N), 
             row.names=NULL)
}
> ddply(df, 'Species', SpeciesStats)
   Species Length Count    Density     delta.N
1        A     11     3 0.10000000          NA
2        A     12     2 0.06666667 -0.03333333
3        B     12     1 0.03333333          NA
4        B     13     3 0.10000000  0.06666667
5        B     14     2 0.06666667 -0.03333333
6        C     11     3 0.10000000          NA
7        C     12     3 0.10000000  0.00000000
8        C     14     1 0.03333333 -0.06666667
9        D     13     3 0.10000000          NA
10       D     14     3 0.10000000  0.00000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...