Как мне отфильтровать data.frame в R по категориальной переменной? - PullRequest
5 голосов
/ 19 февраля 2011

Просто выучить R.

Учитывая data.frame в R с двумя столбцами, одним числовым и одним категориальным, как мне извлечь часть data.frame для использования?

str(ex0331)
'data.frame':   36 obs. of  2 variables:
$ Iron      : num  0.71 1.66 2.01 2.16 2.42 ...
$ Supplement: Factor w/ 2 levels "Fe3","Fe4": 1 1 1 1 1 1 1 1 1 1 ...

По сути, мне нужно иметь возможность оперировать двумя факторами по отдельности;т.е. мне нужна возможность индивидуально определять длину / среднее значение / sd / и т. д. степени удержания железа по типу Supplement (Fe3 или Fe4).

Какой самый простой способ сделать это?

Мне известна команда by().Например, следующее получает кое-что из того, что мне нужно:

by(ex0331, ex0331$Supplement, summary)
ex0331$Supplement: Fe3
     Iron       Supplement
Min.   :0.710   Fe3:18    
1st Qu.:2.420   Fe4: 0    
Median :3.475             
Mean   :3.699             
3rd Qu.:4.472             
Max.   :8.240             
------------------------------------------------------------ 
ex0331$Supplement: Fe4
     Iron        Supplement
Min.   : 2.200   Fe3: 0    
1st Qu.: 3.892   Fe4:18    
Median : 5.750             
Mean   : 5.937             
3rd Qu.: 6.970             
Max.   :12.450      

Но мне нужна большая гибкость.Мне нужно применять axis команды, например, или log() функции по группам.Я уверен, что есть простой способ сделать это;Я просто не вижу этого.Вся документация по манипуляции data.frame, которую я видел, предназначена для числовых, а не для категориальных переменных.

Ответы [ 2 ]

3 голосов
/ 19 февраля 2011

Вы можете получить подмножество ваших данных с помощью индексации или с помощью subset:

ex0331 <- data.frame( iron=rnorm(36), supplement=c("Fe3","Fe4"))

subset(ex0331, supplement=="Fe3")
subset(ex0331, supplement=="Fe4")

ex0331[ex0331$supplement=="Fe3",]

или сразу с split, в результате появится список:

split(ex0331,ex0331$supplement)

Другая вещь, которую вы можете сделать, это использовать tapply, чтобы разделить на множители и затем выполнить функцию:

tapply(ex0331$iron,ex0331$supplement,mean)
        Fe3         Fe4 
-0.15443861 -0.01308835 

Также можно использовать пакет plyr, который имеет множество полезных функций.Например:

library(plyr)
daply(ex0331,.(supplement),function(x)mean(x[1]))
        Fe3         Fe4 
-0.15443861 -0.01308835 

Редактировать

В ответ на отредактированный вопрос вы можете получить журнал железа для каждого дополнения с помощью:

ex0331 <- data.frame( iron=abs(rnorm(36)), supplement=c("Fe3","Fe4"))

tapply(ex0331$iron,ex0331$supplement,log)

или с помощью plyr:

library(plyr)
dlply(ex0331,.(supplement),function(x)log(x$iron))

Оба возвращаются в списке.Я уверен, что есть более простой способ, чем функция-обертка в примере с plyr.

3 голосов
/ 19 февраля 2011

Я бы порекомендовал использовать функцию ddply из пакета plyr, подробный документ доступен онлайн:

> require(plyr)
> ddply( ex0331, .(Supplement), summarise, 
         mean = mean(Iron), 
         sd = sd(Iron), 
         len = length(Iron))

  Supplement       mean        sd len
1        Fe3 -0.3749169 0.2827360   4
2        Fe4  0.1953116 0.7128129   6

Обновление .Чтобы добавить столбец LogIron, где каждая запись представляет собой log() значения Iron, вы просто должны использовать transform:

> transform(ex0331, LogIron = log(Iron))

         Iron Supplement     LogIron
1  0.07185141        Fe3 -2.63315498
2  1.10367297        Fe3  0.09864368
3  0.48592428        Fe3 -0.72170246
4  0.20286918        Fe3 -1.59519393
5  0.80830682        Fe4 -0.21281357

Или создать сводку, которая является «средним»из журнала значений железа, в дополнение ", вы должны сделать:

> ddply( ex0331, .(Supplement), summarise, meanLog = mean(log(Iron)))
  Supplement    meanLog
1        Fe3 -1.0062304
2        Fe4  0.2791507
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...