gpt4 book ai didi

r - sapply() 返回列表而不是向量

转载 作者:行者123 更新时间:2023-12-05 04:09:40 36 4
gpt4 key购买 nike

我有以下数据框-

   name amarks bmarks cmarks
1 A 25 30 40
2 B 45 78 50
3 C 75 72 29
4 D 18 16 70
. . . . .

其中 name 是人名,amarks、bmarks 和 cmarks 是此人在不同考试中的分数。现在我的任务是找出在 amarks、bmarks 和 cmarks 中得分最高的人的名字。我还必须将其存储为矢量。我已经通过以下方式解决了它 -

> max_name <- sapply(marks[,2:4], function(x) {subset(marks, x == max(x,
> na.rm = T), name)})

这给了我正确的答案,但是当我检查 max_name 的数据类型时,我看到它是一个列表,而理想情况下我希望 sapply 返回向量。

以下是我的观察——

class(max_name)

> list

typeof(max_name)

> list

is.vector(max_name)

> vector

有人可以解释一下这里发生的事情吗?我错过了什么吗?我是否需要对我的代码进行任何更改才能返回向量?

最佳答案

您的代码有一些问题:

    数据帧的
  1. subset 方法将 , drop = FALSE 设置为默认值,这意味着您将总是得到一个数据帧作为返回(除非您将明确指定 , drop = TRUE)。因此,您将始终得到一个 list 向量作为结果,因为这是 R 中唯一可以将多个数据帧保存在一起的结构(另外,请注意 ?subset 中的“警告”部分 有关何时以及如果您应该使用它的文档)。
  2. x == max(... 可以返回未知数量的行,因为在每一列中可能有几个值等于最大值。因此,很可能你会得到不同的长度向量作为一个结果,好吧,只有一个 list 可以包含不同大小的向量。如果你只希望每列有一个结果,你可以使用 which.max 例如,也会自动忽略 NA
  3. 最后,您不是很清楚您实际期望的返回是什么而不是列表?如果一列中有不止一行等于最大值,是否需要两个名称?还是只有第一个?无论哪种方式,以下是几个选项

让我们添加一些 NA 和一些等于列最大值的重复行,这样我们就可以看到结果有何不同

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"

或者完全矢量化的解决方案(作为使用外部包、矩阵转换和通常 super 复杂的交换)

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)

marks$name[sapply(marks[, 2:4], which.max)]
# [1] "C" "B" "C"

关于r - sapply() 返回列表而不是向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45529668/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com