数据包含四个字段:id, x1, x2, and x3
。
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
)的最小值
DF$minX <- pmin(DF$x1, DF$x2, DF$x3)
我需要创建一个新字段y
,其定义如下
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"
注意:我们假设没有联系。
答案 0 :(得分:4)
作为一个简单的解决方案,请执行:
which.min
函数apply
返回最小值的索引。如果最小值不唯一,则返回第一个。既然你保证没有领带,这不是问题。
最后,您应该熟悉MARGIN = 1
,对吗? FUN
表示逐行应用函数MARGIN = 2
,而FUN
表示逐列应用for
。这是一个有用的函数,可以避免在处理矩阵时需要apply
循环。由于您的数据框只包含数字/整数值,因此它就像一个矩阵,因此我们可以使用<div ng-init="initObject = {initParam: 'initParamValue', anotherOne: 'value'}"></div>
。
答案 1 :(得分:1)
data.table
解决方案:
# 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
方法来产生相同的(最终)结果。在我从这个问题(see here)开始的问题中,这个解决方案被归功于@ eipi10:
DF %>% mutate(y = apply(.[,2:4], 1, function(x) names(x)[which.min(x)]))
当应用于1e6行数据帧(我的索尼笔记本电脑中大约17秒)时,此解决方案与原始答案中提供的data.table
时间大致相同。
答案 2 :(得分:1)
以下是使用pmin
和max.col
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