2013-07-09 2 views
1

У меня есть data.frame с 3 столбцами, каждый из которых можно рассматривать как фактор. Я хотел бы вычислить некоторую статистику на data.frame и сохранить ее в новом фрейме. Чтобы быть более конкретным, у меня есть следующие поля:Векторизованные вычисления метаданных на основе нескольких столбцов на R data.frame

obs, len, src 
A 10 X 
B 10 Y 

Я хотел бы вычислить разбивку каждого источника на каждой длине (т.е. какой процент наблюдений из источника X, которые имеют длину 10 являются «А» , «B» и т. Д.)

Очевидным подходом к этому является использование двух циклов для повторения по длинам и источникам, а затем использования nrow() и count() для получения значений, которые мне нужно вычислить , так:

relevant_subset <- data[data$src==source & data$len==length,] 
breakdown_info <- count(relevant_subset) 
breakdown_info$frac <- breakdown_info$freq/nrow(relevant_subset) 

Есть ли способ избежать использования цикла double for и использовать более v экторированный подход? Есть ли разумный способ предварительного выделения нового фрейма, который будет содержать измененный breakdown_info для каждой длины и источника?

+0

Вы пробовали 'table'? – asb

ответ

1

Это то, что пакет plyr был сделан для!

Формат: <input_type><output_type>ply. Например, если входной сигнал data.frame и вы хотите, чтобы выход был data.frame, используйте ddply.

Чтобы использовать его, вы указываете вход data.frame, столбцы для группировки, а затем функцию, которая строит data.frame из каждой группы. Полученный результат data.frames, прилагаемый к колонкам группировки, собран вместе с выходом data.frame.

В то похожее на вашем примере, вы могли бы сделать

require(plyr) 
a <- data.frame(
    obs=factor(c('A','A','A','B','B')), 
    len=c(10,10,10,10,210), 
    src=factor(c('X','X','Y','Y','Z'))) 

затем

z <- ddply(
    a, 
    .(obs), 
    function(df){ 
    data.frame(mean.len=mean(df$len)) 
    }) 

будет производить

data.frame(
    obs=c('A', 'B'), 
    mean.length(10, 110)) 

в то время как

ddply(a, .(src), function(df){ 
    data.frame(
    num.obs.A = sum(df$obs == 'A'), 
    num.obs.B = sum(df$obs == 'B'))}) 

будет производить

data.frame(
    src=c('X','Y', 'Z'), 
    num.obs.A = c(3,1,0), 
    num.obs.B = c(0,1,1)) 

Сайт http://plyr.had.co.nz/ имеет хорошую документацию тоже.

+0

Спасибо, @momeara, это сработало для меня! Окончательная форма моего кода выглядит так: 'ddply (data,. (Length, source), function (df) {' 'code <- levels (df $ DSSP)' 'total <- length (df $ DSSP) ' ' foo <- data.frame (x = 0) ' ' colnames (foo) <- paste ("num.", Codes [1], sep = "") ' ' для (код в коды) {' ' numRes <- sum (df $ DSSP == code) ' ' foo [paste ("num.", code, sep = "")] <- numRes' 'foo [paste (" frac . ", code, sep =" ")] <- numRes/total' '} ' ' return (foo) ' '}) ' – weitzner

+0

Извините за форматирование wow выше! – weitzner

2

aggregate является вашим другом для решения этих задач:

Пример данных:

set.seed(23) 
test <- data.frame(
    obs=sample(LETTERS[1:2],20,replace=TRUE), 
    len=sample(c(10,20),20,replace=TRUE), 
    src=sample(LETTERS[24:25],20,replace=TRUE) 
) 

агрегировать его:

aggregate(obs ~ src + len,data=test, function(x) prop.table(table(x))) 

    src len  obs.A  obs.B 
1 X 10 0.6000000 0.4000000 
2 Y 10 0.2000000 0.8000000 
3 X 20 0.2500000 0.7500000 
4 Y 20 0.1666667 0.8333333 
+0

'aggregate' может быть вашим врагом здесь, если вы не знаете, что делаете, или не смотрите' '' '' ваш результат 'aggregate'. В таких ситуациях я думаю, что вывод для 'do.call (data.frame, aggregate (obs ~ src + len, data = test, function (x) prop.table (table (x))))' is больше того, с кем большинство людей будет чувствовать себя комфортно. – A5C1D2H2I1M1N2O1R2T1

0

Вы не указали причину, по которой вы хотите получить data.frame здесь как вывод. Возможно, это лучше для вас, возможно, нет. Вы также не совсем поняли, что такое пропорции, но я думаю, что следующее может решить вашу проблему лучше всего.

prop.table(table(test)) 

Вы можете ввести несколько иначе и играть с порядком столбцов, так что то, что вы хотите сравнить наиболее легко изучены. Но этот вывод представляет собой 3-мерный массив и немного отличается от data.frame.

(пример альтернативного использования)

prop.table(with(test, table(src, obs, len))) 
Смежные вопросы