2012-03-01 13 views
6

Estoy usando by para aplicar una función a un rango columnas de un marco de datos basado en un factor. Todo funciona perfectamente bien si uso mean() como la función pero si uso median() me sale un error del tipo "Error en median.default (x): necesito datos numéricos" incluso si no tengo NA en los datos marco.Cómo aplicar una función a un subconjunto de columnas en r?

La línea que funciona mediante mean():

by(iris[,1:3], iris$Species, function(x) mean(x,na.rm=T)) 

> by(iris[,1:3], iris$Species, function(x) mean(x,na.rm=T)) 
iris$Species: setosa 
Sepal.Length Sepal.Width Petal.Length 
     5.006  3.428  1.462 
------------------------------------------------------------ 
iris$Species: versicolor 
Sepal.Length Sepal.Width Petal.Length 
     5.936  2.770  4.260 
------------------------------------------------------------ 
iris$Species: virginica 
Sepal.Length Sepal.Width Petal.Length 
     6.588  2.974  5.552 
Warning messages: 
1: mean(<data.frame>) is deprecated. 
Use colMeans() or sapply(*, mean) instead. 
2: mean(<data.frame>) is deprecated. 
Use colMeans() or sapply(*, mean) instead. 
3: mean(<data.frame>) is deprecated. 
Use colMeans() or sapply(*, mean) instead. 

Pero si uso median() (nótese el na.rm=T option):

> by(iris[,1:3], iris$Species, function(x) median(x,na.rm=T)) 
Error in median.default(x, na.rm = T) : need numeric data 

Sin embargo, si en lugar de elegir la gama [,1:3] de columnas que elegir sólo una de las columnas que funciona:

> by(iris[,1], iris$Species, function(x) median(x,na.rm=T)) 
iris$Species: setosa 
[1] 5 
------------------------------------------------------------ 
iris$Species: versicolor 
[1] 5.9 
------------------------------------------------------------ 
iris$Species: virginica 
[1] 6.5 

¿Cómo puedo lograr este comportamiento al seleccionar un rango de columnas?

+0

Los mensajes de advertencia se obtiene cuando se use 'mean' debería ser una buena pista de que, de hecho, todo no funciona" bien ". Esta reciente [respuesta] (http://stackoverflow.com/a/9424510/324364) mía podría arrojar algo de luz sobre esto para usted. – joran

Respuesta

4

Está utilizando una estrategia de aplicación dividida cuando usa by. Los objetos que se pasan a la función son dataframes y recibirá la advertencia y el error debido a la inexistencia de median.data.frame y la inminente inexistencia de mean.data.frame. Podría funcionar mejor si usted utiliza aggregate:

> aggregate(iris[,1:3], iris["Species"], function(x) mean(x,na.rm=T)) 
    Species Sepal.Length Sepal.Width Petal.Length 
1  setosa  5.006  3.428  1.462 
2 versicolor  5.936  2.770  4.260 
3 virginica  6.588  2.974  5.552 
> aggregate(iris[,1:3], iris["Species"], function(x) median(x,na.rm=T)) 
    Species Sepal.Length Sepal.Width Petal.Length 
1  setosa   5.0   3.4   1.50 
2 versicolor   5.9   2.8   4.35 
3 virginica   6.5   3.0   5.55 

aggregate trabajos sobre los vectores columna de forma individual y luego tabula los resultados.

+0

Gracias. Ahora funciona. Ahora tengo la duda sobre cuál es la diferencia entre: 'agregado (iris [, 1: 3], iris [" Especie "], función (x) mediana (x, na.rm = T))' y ' agregado (iris [, 1: 3], iris $ Especie, función (x) mediana (x, na.rm = T)) '. El segundo devuelve este error 'Error en aggregate.data.frame (iris [, 1: 3], iris $ Especie, función (x) mediana (x,: 'por' debe ser una lista' – pedrosaurio

+1

@pedrosaurio El error el mensaje lo dice todo. 'iris [" Especie "]' es una lista (un marco de datos, en realidad), mientras que 'iris $ Especie' no lo es. Puedes verificar esto usando' str() '. – joran

+1

Pensé en agregar un nota diciendo que estabas usando '$ Species' que es equivalente a' [["Species"]] 'que devuelve un vector atómico y que yo estaba usando' ["Species"] 'que devuelve una lista. Supongo que debería lo he hecho –

1

La pregunta original está respondida. Si, sin embargo, el rango pasa a ser (en su lugar) todas las columnas excepto los especificados como la variable independiente en la fórmula, funciona la notación fórmula punto, y representa una alternativa ingeniosa:

> aggregate(. ~ Species, data = iris, mean) 
    Species Sepal.Length Sepal.Width Petal.Length Petal.Width 
1  setosa  5.006  3.428  1.462  0.246 
2 versicolor  5.936  2.770  4.260  1.326 
3 virginica  6.588  2.974  5.552  2.026 

> aggregate(. ~ Species, data = iris, median) 
    Species Sepal.Length Sepal.Width Petal.Length Petal.Width 
1  setosa   5.0   3.4   1.50   0.2 
2 versicolor   5.9   2.8   4.35   1.3 
3 virginica   6.5   3.0   5.55   2.0 
Cuestiones relacionadas