首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从R中的最小值创建一个新变量

从R中的最小值创建一个新变量
EN

Stack Overflow用户
提问于 2016-05-12 18:57:20
回答 3查看 576关注 0票数 2

数据包含四个字段:id, x1, x2, and x3

代码语言:javascript
复制
id <- c(1,2,3,4,5,6,7,8,9,10)
x1 <- c(2,4,5,3,6,4,3,6,7,7)
x2 <- c(0,1,2,6,7,6,0,8,2,2)
x3 <- c(5,3,4,5,8,3,4,2,5,6)

DF <- data.frame(id, x1,x2,x3)

在我问这个问题之前,让我创建一个新的字段(minX),它是(x1,x2,x3)的min。

代码语言:javascript
复制
DF$minX <- pmin(DF$x1, DF$x2, DF$x3)

我需要创建一个新字段y,定义如下

代码语言:javascript
复制
if min(x1,x2,x3) = x1, then y = "x1"
if min(x1,x2,x3) = x2, then y = "x2"
if min(x1,x2,x3) = x3, then y = "x3"

注:我们假定没有联系。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-12 19:21:07

data.table解决方案:

代码语言:javascript
复制
# create variables
id <- c(1,2,3,4,5,6,7,8,9,10)
x1 <- c(2,4,5,3,6,4,3,6,7,7)
x2 <- c(0,1,2,6,7,6,0,8,2,2)
x3 <- c(5,3,4,5,8,3,4,2,5,6)
DF <- data.frame(id, x1,x2,x3)

# load package and set data table, calculating min
library(data.table)
setDT(DF)[, minx := apply(.SD, 1, min), .SDcols=c("x1", "x2", "x3")]

# Create variable with name of minimum
DF[, y := apply(.SD, 1, function(x) names(x)[which.min(x)]), .SDcols = c("x1", "x2", "x3")]

# call result
DF
##     id x1 x2 x3 minx  y
 1:  1  2  0  5    0 x2
 2:  2  4  1  3    1 x2
 3:  3  5  2  4    2 x2
 4:  4  3  6  5    3 x1
 5:  5  6  7  8    6 x1
 6:  6  4  6  3    3 x3
 7:  7  3  0  4    0 x2
 8:  8  6  8  2    2 x3
 9:  9  7  2  5    2 x2
10: 10  7  2  6    2 x2

可以直接调用最后一步,而无需计算minx。请注意,data.table在大数据集中通常是快速的。

########编辑以添加: DPLYR方法#########

为了完整起见,这将是一个生成相同(最终)结果的dplyr方法。在我从这个问题开始的一个问题中,这个解决方案被认为是@eipi10 10,(see here)

代码语言:javascript
复制
DF %>% mutate(y = apply(.[,2:4], 1, function(x) names(x)[which.min(x)]))

当应用于1e6行数据帧(在我的索尼笔记本上大约17秒)时,此解决方案与原始答案中提供的data.table解决方案相同。

票数 1
EN

Stack Overflow用户

发布于 2016-05-12 19:05:52

作为一个简单的解决方案,请:

代码语言:javascript
复制
VARS <- colnames(DF)[-1]
y <- VARS[apply(DF[, -1], MARGIN = 1, FUN = which.min)]
DF$y <- y

函数which.min返回最小值的索引。如果最小值不是唯一的,则返回第一个。既然你保证没有平手,这就不是问题了。

最后,您应该熟悉apply,对吗?MARGIN = 1意味着按行应用函数,而MARGIN = 2则意味着应用FUN列。这是一个有用的函数,以避免在处理矩阵时需要一个for循环。因为您的数据帧只包含数值/整数值,所以它就像一个矩阵,因此我们可以使用apply

票数 4
EN

Stack Overflow用户

发布于 2016-05-13 01:43:49

下面是使用pminmax.col的另一个选项

代码语言:javascript
复制
library(data.table)
setDT(DF)[, c("minx", "y") := list(do.call(pmin, .SD), 
             names(.SD)[max.col(-1*.SD)]), .SDcols= x1:x3]
DF
#    id x1 x2 x3 minx  y
# 1:  1  2  0  5    0 x2
# 2:  2  4  1  3    1 x2
# 3:  3  5  2  4    2 x2
# 4:  4  3  6  5    3 x1
3 5:  5  6  7  8    6 x1
# 6:  6  4  6  3    3 x3
# 7:  7  3  0  4    0 x2
# 8:  8  6  8  2    2 x3
# 9:  9  7  2  5    2 x2
#10: 10  7  2  6    2 x2
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37195322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档