如何有条件地按行比较数据行并将不同的结果输出到其他列?
请参阅下面的dataset
,
第1行的den
为1,开始将每行的权重与第1行的权重进行比较,将每行的体积与第1行的体积进行比较。
首先检查某行的Weight
是否高于第1行的权重,第1行的higher
列将变为1,否则检查某行的Volume
是否为比第1行的Volume
低1.0,第1行的下一列将变为1。
在满足其中任何一个条件之前,继续比较下一行和下一行......如果第2行满足任一条件,则转到第3行,如果符合Row的任一条件3,继续行到第4行.....等等。
如果满足其中一个条件(第1行的higher
或lower
列之一== 1),请转到den==1
第3行的下一行在这种情况下。第6行。
{1}}列用于记录第1行' s {{1}时行howhigh
与第1行' s Weight
之间的差异}。 Weight
列用于记录满足条件的行差异(例如:在higher == 1
中,第1行' s between
为5,因为条件符合第6行的要求,所以Expected Outcome
,第3行的between
为3,因为条件符合第6行所以6 - 1 = 5
)
然后between
会变成6 - 3 = 3
从dataset
获取第14行,Expected Outcome
,因为第18行的Expected Outcome
更高。 higher==1
为Weight
,因为第14行和第18行的howhigh
差异为0.0649
,Weight
为0.0649
,因为between
如何实现这种矢量化方式来提高计算速度? 提前致谢。
数据集
4
预期结果
18-14=4
答案 0 :(得分:2)
# Your data
dat <- structure(list(Weight = c(5.1626, 5.1615, 5.16, 5.1593, 5.1592, 5.1635, 5.1608, 5.1602, 5.1582, 5.1563, 5.1578, 5.1589, 5.1578, 5.1591, 5.1585, 5.1572, 5.1565, 5.224, 5.154, 5.1539, 5.152, 5.145, 5.1455, 5.1461, 5.147, 5.1449, 5.1423, 6.1429, 5.1425, 5.1433), Volume = c(5.1594, 5.1559, 5.1574, 5.1582, 5.1572, 5.158, 5.158, 4.0565, 5.1554, 5.1547, 5.155, 5.156, 3.1553, 5.1554, 5.1563, 5.1557, 5.152, 5.1518, 5.1505, 5.1488, 5.1408, 5.142, 5.142, 5.1435, 5.1437, 5.1378, 5.1385, 5.1401, 5.1399, 5.1403), den = c(1L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), higher = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), lower = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), between = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), howhigh = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("Weight", "Volume", "den", "higher", "lower", "between", "howhigh"), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30"))
我在data.frame中添加了一个rownumber,以便在apply中更方便地访问,然后我只使用den == 1
的行来创建一个用于循环的新变量。
dat$rownum <- 1:nrow(dat)
newd <- dat[dat$den == 1,]
# Weight Volume den higher lower between howhigh rownum
#1 5.1626 5.1594 1 1 0 0 0 1
#3 5.1600 5.1574 1 1 0 0 0 3
#6 5.1635 5.1580 1 1 0 0 0 6
#11 5.1578 5.1550 1 1 0 0 0 11
#14 5.1591 5.1554 1 1 0 0 0 14
#19 5.1540 5.1505 1 1 0 0 0 19
#30 5.1433 5.1403 1 1 0 0 0 30
功能:
out <- t(apply(newd, 1, function(d){
rownum <- d["rownum"]
a <- which(dat$Weight > d["Weight"])
a <- a[a > rownum][1]
b <- which((dat$Volume - d["Volume"]) <= -1.0)
b <- b[b > rownum][1]
pick <- ifelse(!is.na(b), ifelse(a < b, "a", "b"), "a")
if( pick == "a"){
d["higher"] <- 1
d["howhigh"] <- dat$Weight[a] - d["Weight"]
d["between"] <- a - rownum
} else {
d["lower"] <- 1
d["between"] <- b - rownum
}
d[is.na(d)] <- 0
d
}))
out
# Weight Volume den higher lower between howhigh rownum
#1 5.1626 5.1594 1 1 0 5 0.0009 1
#3 5.1600 5.1574 1 1 0 3 0.0035 3
#6 5.1635 5.1580 1 0 1 2 0.0000 6
#11 5.1578 5.1550 1 1 0 1 0.0011 11
#14 5.1591 5.1554 1 1 0 4 0.0649 14
#19 5.1540 5.1505 1 1 0 9 0.9889 19
#30 5.1433 5.1403 1 1 0 0 0.0000 30
dat[dat$den == 1,] <- out # replace old rows with new ones
dat[,-8] # remove the rownum column