2012-04-24 70 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