2012-04-24 72 views
4

我正在尝试编写一些代码,用于识别每行最大的两个值并提供它们的列号和值。查找列号并将其值排在第二个最高值

df = data.frame(car = c (2,1,1,1,0), bus = c (0,2,0,1,0), 
       walk = c (0,3,2,0,0), bike = c(0,4,0,0,1)) 

我已经成功地得到它的使用maxmax.col函数的最大值做到这一点。

df$max = max.col(df,ties.method="first") 
df$val = apply(df[ ,1:4], 1, max) 

就我所知,第二个最高值没有等效函数,所以这样做使事情有点棘手。使用此代码提供了第二高的价值,但(重要的)不是在有关系的情况下。另外它看起来有风险。

sec.fun <- function (x) { 
    max(x[x!=max(x)]) 
} 

df$val2 <- apply(df[ ,1:4], 1, sec.fun) 

理想的解决方案将不涉及删除任何原始数据,可用于寻找第三,第四......最高值,但这些都不是必不可少的要求。

回答

17

试试这个:

# a function that returns the position of n-th largest 
maxn <- function(n) function(x) order(x, decreasing = TRUE)[n] 

这是一个封闭,所以你可以使用这样的:

> # position of the largest 
> apply(df, 1, maxn(1)) 
[1] 1 4 3 1 4 
> # position of the 2nd largest 
> apply(df, 1, maxn(2)) 
[1] 2 3 1 2 1 
> 
> # value of the largest 
> apply(df, 1, function(x)x[maxn(1)(x)]) 
[1] 2 4 2 1 1 
> # value of the 2nd largest 
> apply(df, 1, function(x)x[maxn(2)(x)]) 
[1] 0 3 1 1 0 

为什么这里使用封闭更新

原因之一是,你可以定义一个函数,例如:

max2 <- maxn(2) 
max3 <- maxn(3) 

然后,用它

> apply(df, 1, max2) 
[1] 2 3 1 2 1 
> apply(df, 1, max3) 
[1] 3 2 2 3 2 

我不知道,如果优势很明显,但我喜欢这种方式,因为这是更具功能性的方式。

+0

好的,我还没有喝咖啡,但是你的'maxn'超过'maxn <-function(x,n = 1)的顺序(x,递减= TRUE)[n]'有没有优势? – 2012-04-24 12:04:35

+0

谢谢。查看更新。 – kohske 2012-04-24 12:11:45

+0

谢谢,我已经试过了,它似乎工作得很好。对其他人的一个注意事项是,将这些值添加到现有数据框时,必须指定列范围,如原始示例中那样。 – BuckyOH 2012-04-24 12:17:30