1

我有一个包含 12 套股票行情每月回报的动物园对象。我想获得每个月表现最好的股票的系列名称,或者至少是列的名称。我一直在尝试通过逐行应用 max 函数来做到这一点。如何获取列名?

#Apply 'max' function across each row. I need to get the col number out of this.
apply(tsPctChgs, 1, max, na.rm = TRUE)
4

2 回答 2

4

通常的答案是通过which.max(),但是请注意,如果有两个或多个观察值取最大值,这将只返回最大值中的第一个。

另一种方法是which(x == max(x)),它将返回所有取平局结果中最大值的值。

然后,您可以使用返回的索引来选择系列最大值。处理NAs 将在下面介绍,以尽量保持最初的讨论简单。

require("zoo")
set.seed(1)
m <- matrix(runif(50), ncol = 5)
colnames(m) <- paste0("Series", seq_len(ncol(m)))
ind <- seq_len(nrow(m))

mz <- zoo(m, order.by = ind)

> apply(mz, 1, which.max)
 1  2  3  4  5  6  7  8  9 10 
 3  5  5  1  4  1  1  2  3  2

> apply(mz, 1, function(x) which(x == max(x)))
 1  2  3  4  5  6  7  8  9 10 
 3  5  5  1  4  1  1  2  3  2

所以用它来选择系列名称

i1 <- apply(mz, 1, function(x) which(x == max(x)))
colnames(mz)[i1]

> i1 <- apply(mz, 1, function(x) which(x == max(x)))
> colnames(mz)[i1]
 [1] "Series3" "Series5" "Series5" "Series1" "Series4" "Series1" "Series1"
 [8] "Series2" "Series3" "Series2"

处理并列最大值

为了说明不同的行为,将第 1 个月(系列 3)的最大值复制到系列 1

mz2 <- mz ## copy
mz2[1,1] <- mz[1,3]
mz2[1,]

> mz2[1,]

1 0.9347052 0.2059746 0.9347052 0.4820801 0.8209463

现在再次尝试这两种方法

> apply(mz2, 1, which.max)
 1  2  3  4  5  6  7  8  9 10 
 1  5  5  1  4  1  1  2  3  2 
> apply(mz2, 1, function(x) which(x == max(x)))
$`1`
Series1 Series3 
      1       3
.... ## truncated output ###

注意如何which.max只返回系列 1 中的最大值。

要使用这种方法来选择系列名称,您需要对返回的列表应用一些东西apply(),例如

i2 <- apply(mz2, 1, function(x) which(x == max(x)))
lapply(i2, function (i, zobj) colnames(zobj)[i], zobj = mz2)

$`1`
[1] "Series1" "Series3"

$`2`
[1] "Series5"

$`3`
[1] "Series5"

$`4`
[1] "Series1"

$`5`
[1] "Series4"

$`6`
[1] "Series1"

$`7`
[1] "Series1"

$`8`
[1] "Series2"

$`9`
[1] "Series3"

$`10`
[1] "Series2"

处理NA_

由于您具有 s 的潜力NA,因此我将执行以下操作:

apply(mz, 1, which.max, na.rm = TRUE) ## as you did already
apply(mz, 1, function(x, na.rm = TRUE) {
               if(na.rm) {
                 x <- x[!is.na(x)]
               }
               which(x == max(x))
             })
于 2013-07-22T16:11:18.453 回答
3

由于apply转换为矩阵,我将使用rollapplywith width=1

require("zoo")
set.seed(1)
m <- matrix(runif(50), ncol=5)
mz <- setNames(zoo(m, seq(nrow(m))), paste0("Series",seq(ncol(m))))
rollapply(mz, 1, function(r) colnames(mz)[which.max(r)], by.column=FALSE)
于 2013-07-22T16:38:51.960 回答