你必須與你的代碼的幾個問題:
subset
爲dataframes方法, drop = FALSE
設置爲默認值,這意味着你將總是會得到回報一個數據幀(除非你明確指定, drop = TRUE
) 。因此,您總是會得到一個list
向量,因爲這是R中唯一可以同時保存多個數據幀的結構(同時請注意?subset
文檔中的「Warning」部分,說明何時使用,如果應該使用它)。
x == max(...
可以返回未知數量的行,因爲在每列中可能有幾個值等於最大值。因此,大多數情況下,您會得到不同的長度向量,並且,只有list
可以保存不同大小的向量。如果您只希望每列有單個結果,則可以使用which.max
,這也會自動忽略NA
s。
- 最後,你不是很清楚你實際期望的是什麼,而不是一個列表?如果列中有多個行等於最大值,那麼您是否想要這兩個名稱?還是隻有第一個?非此即彼的方式,下面是幾個選項
讓我們添加一些NA
S和它等於列的一些重複的行MAXS,所以我們可以看到結果基本不同
marks <- read.table(text = "name amarks bmarks cmarks
1 A NA 30 40
2 B 45 78 50
3 C 75 NA 70
4 D 75 16 70", header = TRUE, stringsAsFactors = FALSE)
marks
# name amarks bmarks cmarks
# 1 A NA 30 40
# 2 B 45 78 50
# 3 C 75 NA 70
# 4 D 75 16 70
,如果你想所有的name
小號,我們可以只添加unlist
到您的代碼
unlist(sapply(marks[, 2:4], function(x) {subset(marks, x == max(x, na.rm = TRUE), name)}))
# amarks.name1 amarks.name2 bmarks.name cmarks.name1 cmarks.name2
# "C" "D" "B" "C" "D"
替代方式達到相同的無使用subset
marks$name[unlist(sapply(marks[, 2:4], function(x) which(x == max(x, na.rm = TRUE))))]
## [1] "C" "D" "B" "C" "D"
或者甚至(向量化/過併發症權衡)
marks$name[which(sapply(marks[, 2:4],
function(x) x == max(x, na.rm = TRUE)), arr.ind = TRUE)[, "row"]]
## [1] "C" "D" "B" "C" "D"
或完全矢量化溶液(在交換使用外部封裝,矩陣變換和通常超過-complication)
marks$name[which(marks[, 2:4] == matrixStats::colMaxs(as.matrix(marks[, 2:4]),
na.rm = TRUE)[col(marks[, 2:4])],
arr.ind = TRUE)[, "row"]]
## [1] "C" "D" "B" "C" "D"
不過,如果你只是想第一馬克西媽媽每列,我們可以簡化爲(其中還處理NA
s)
marks$name[sapply(marks[, 2:4], which.max)]
# [1] "C" "B" "C"
首先'list' *是一個向量。其次,當你做'x == max'之類的事情時,你永遠不知道會得到多少結果。它可以是1或1千。在R中,只有一個列表可以存儲不同大小的向量,因此R返回一個列表。如果您總是希望每列有一個結果,請參閱'?which.max'。另外,你期望的結果是什麼?不僅僅是'sapply(標記[,2:4],max,na.rm = TRUE)'就足夠了? –
或者'也許'標記$ name [sapply(marks [,2:4],which.max)]''。另外,'subset'返回一個數據幀。理論上,您可以在代碼的末尾添加',drop = TRUE',並且如果每列總是有一個'max',那麼您將得到一個字符向量。 –
感謝大衛,幫助。 – user1305398