我有两列,每行的总和为1(它们是两个类之一的概率)。我需要找到符合条件的列号。
C1 C2
0.4 0.6
0.3 0.7
1 0
0.7 0.3
0.1 0.9
例如,如果我需要找到数字> gt = 0.6的列, 在上表中,它应该导致:
2
2
1
1
2
答案 0 :(得分:5)
您可以利用TRUE
= 1和FALSE
= 0的事实:
> df <- read.table(textConnection("C1 C2
+ 0.4 0.6
+ 0.3 0.7
+ 1 0
+ 0.7 0.3
+ 0.1 0.9"), header = T)
> (df$C2 >= 0.6) + 1
[1] 2 2 1 1 2
答案 1 :(得分:5)
感谢您提出这个有趣的问题。以下是使用apply
的想法。
apply(dat, 1, function(x) which(x >= 0.6))
# [1] 2 2 1 1 2
数据强>
dat <- read.table(textConnection("C1 C2
0.4 0.6
0.3 0.7
1 0
0.7 0.3
0.1 0.9"), header = T)
<强>基准强>
我为原始数据框dat
和5000行dat2
的数据框执行了基准测试。结果如下。我感到有点尴尬,我的apply
方法是最慢的。
如果有人知道如何改进我的基准测试方式,请告诉我。
library(microbenchmark)
# Benchmark 1
perf <- microbenchmark(m1 = {apply(dat, 1, function(x) which(x >= 0.6))},
m2 = {ifelse(dat$C1 <= 0.4, 2, 1)},
m3 = {(dat$C2 >= 0.6) + 1},
m4 = {(which(t(dat) >= 0.6) + 1) %% ncol(dat) + 1},
m5 = {((dat>=0.6) %*% c(1,2))[, 1]},
m6 = {m <- which(dat >= 0.6, arr.ind = TRUE)
m[order(m[, 1]), ][, 2]},
m7 = {max.col(dat >= 0.6)})
perf
# Unit: microseconds
# expr min lq mean median uq max neval
# m1 58.602 65.0280 88.34563 67.5985 70.6825 1746.246 100
# m2 9.253 12.8515 15.45772 13.8790 14.9080 49.349 100
# m3 4.112 5.6540 6.59015 6.1690 7.1970 23.132 100
# m4 30.844 35.7270 40.29682 38.0405 40.8670 134.683 100
# m5 23.647 26.7310 30.13404 27.7590 29.8160 77.109 100
# m6 49.863 53.4620 61.31148 56.5460 59.8875 168.610 100
# m7 37.012 40.0960 45.36537 42.1530 45.2370 97.671 100
# Benchmark 2
dat2 <- dat[rep(1:5, 1000), ]
perf2 <- microbenchmark(m1 = {apply(dat2, 1, function(x) which(x >= 0.6))},
m2 = {ifelse(dat2$C1 <= 0.4, 2, 1)},
m3 = {(dat2$C2 >= 0.6) + 1},
m4 = {(which(t(dat2) >= 0.6) + 1) %% ncol(dat2) + 1},
m5 = {((dat2 >= 0.6) %*% c(1,2))[, 1]},
m6 = {m <- which(dat2 >= 0.6, arr.ind = TRUE)
m[order(m[, 1]), ][, 2]},
m7 = {max.col(dat2 >= 0.6)})
perf2
# Unit: microseconds
# expr min lq mean median uq max neval
# m1 13842.995 14830.2380 17173.18941 15716.2125 16551.8095 165431.735 100
# m2 133.140 146.7630 168.86722 160.6420 179.9195 314.602 100
# m3 22.104 25.7030 31.93827 28.0160 33.9280 67.341 100
# m4 156.787 179.6620 212.97310 210.5055 234.6665 320.257 100
# m5 131.598 148.8195 173.42179 164.2410 189.9440 286.843 100
# m6 403.019 439.2600 496.25370 472.6735 549.0110 791.646 100
# m7 140.337 156.7870 270.48048 179.4055 208.9635 8631.503 100
答案 2 :(得分:3)
这是使用矩阵多次
(dt>=0.6)%*%c(1,2)
[,1]
[1,] 2
[2,] 2
[3,] 1
[4,] 1
[5,] 2
答案 3 :(得分:3)
如果我考虑超过1
列的情况可以满足条件,那么which
将是更好的选择。
我修改了数据,以便列1
和2
满足行3
中的条件。
# Data
df <- read.table(text = "C1 C2
0.4 0.6
0.3 0.7
1 1
0.7 0.3
0.1 0.9", header = T, stringsAsFactors = F)
# Use of which with arr.ind = TRUE
which(df >= 0.6, arr.ind = TRUE)
# Result shows row number 3 twice
# row col
#[1,] 3 1
#[2,] 4 1
#[3,] 1 2
#[4,] 2 2
#[5,] 3 2
#[6,] 5 2
答案 4 :(得分:1)
使用三元函数
ifelse(daf$C1<=0.4, 2, 1)
#[1] 2 2 1 1 2
答案 5 :(得分:1)
这是使用模运算符%%
的另一种可能性:
(which(t(df) >= 0.6) + 1) %% ncol(df) + 1
#[1] 2 2 1 1 2
df <- read.table(text =
"C1 C2
0.4 0.6
0.3 0.7
1 0
0.7 0.3
0.1 0.9", header = T)