【问题标题】:How to apply a function to a subset of columns in r?如何将函数应用于r中的列子集?
【发布时间】:2012-03-01 16:25:26
【问题描述】:

我正在使用by 根据一个因素将函数应用于数据框的范围列。如果我使用mean() 作为函数,一切都运行良好,但如果我使用median(),我会收到 "Error in median.default(x) : need numeric data" 类型的错误,即使我的数据框中没有 NA。

使用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. 

但如果我使用median()(注意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

但是,如果我不选择列的范围[,1:3],而是只选择它有效的列之一:

> 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

如何在选择一系列列时实现此行为?

【问题讨论】:

  • 您在使用mean 时收到的警告消息应该是一个强有力的线索,事实上,一切都不是“正常”的。我最近的answer 可能会为您提供一些启示。

标签: r


【解决方案1】:

当您使用by 时,您使用的是拆分应用策略。传递给函数的对象是数据帧,由于median.data.frame 不存在并且mean.data.frame 即将不存在,您会收到警告和错误。如果您使用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 单独处理列向量,然后将结果制成表格。

【讨论】:

  • 谢谢。现在可以了。我现在只是怀疑:aggregate(iris[,1:3], iris["Species"], function(x) median(x,na.rm=T))aggregate(iris[,1:3], iris$Species, function(x) median(x,na.rm=T)) 之间有什么区别。第二个返回这个错误Error in aggregate.data.frame(iris[, 1:3], iris$Species, function(x) median(x, : 'by' must be a list
  • @pedrosaurio 错误信息说明了一切。 iris["Species"] 是一个列表(实际上是一个数据框),而 iris$Species 不是。您可以使用str() 验证这一点。
  • 我想添加一个注释,说明您使用的是$Species,它相当于返回原子向量的[["Species"]],而我使用的是返回列表的["Species"]。我想我应该这样做。
【解决方案2】:

回答了原来的问题。但是,如果范围恰好是(而不是)除公式中指定为自变量的列之外的所有列,则点公式表示法有效,并代表了一个不错的选择:

> 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

【讨论】:

    猜你喜欢
    • 2019-03-27
    • 2020-08-11
    • 1970-01-01
    • 2019-01-14
    • 2020-02-17
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多