我有以下输入:
id <- c("a", "b", "c", "d")
target <- seq(from = 100, to = 400, length.out = 4)
a <- c(300, 304, 100, 405)
b <- c(300, 104, 100, 405)
c <- c(85, 304, 500, 405)
df <- as.data.frame(cbind(id, target, a, b, c))
我想添加一个新列&#34;列&#34;这表示每行,哪些列&#34; a&#34;,&#34; b&#34;,&#34; c&#34;将是第一列值小于目标解决方案的列。 请求的输出如下所示:
必需输出:
df$column <- c("c", "b", "a", "NA")
df
我想到了如果每行都检查一下,并使用apply函数将其应用于所有行。但是abc列很长(第20轮,因此需要一个循环),行数约为4.000。 有没有人知道如何解决它?
答案 0 :(得分:5)
您可以按照以下方式执行此操作:
1)创建一个逻辑矩阵,指示“a”,“b”或“c”列中的值是否小于目标列:
m <- df[,3:5] < df[,2]
2)创建一个整数向量,这是这三列的第一个名称,其值小于max.col
的目标列,并确保NA
使用[c(TRUE,NA)[1 + (rowSums(m) == 0)]]
mc <- max.col(m, ties.method = 'first')[c(TRUE,NA)[1 + (rowSums(m) == 0)]]
3)将名称分配给新列:
df$column <- names(df[,3:5])[mc]
给出:
> df
id target a b c column
1 a 100 300 300 85 c
2 b 200 304 104 304 b
3 c 300 100 100 500 a
4 d 400 405 405 405 <NA>
我将步骤分开,以使代码更清晰。但是你当然可以更好地整合它:
m <- df[,3:5] < df[,2]
df$column <- names(df[,3:5])[max.col(m, ties.method = 'first')[c(TRUE,NA)[1 + (rowSums(m) == 0)]]]
答案 1 :(得分:3)
这是使用which
的另一个矢量化解决方案。这基本上是target
更大的所有事件,并使用duplicated
函数获取第一个实例。
indx <- which(df[, 3:5] < df[, 2], arr.ind = TRUE)
indx2 <- indx[!duplicated(indx[, "row"]),]
df[indx2[, "row"], "column"] <- names(df)[3:5][indx2[, "col"]]
df
# id target a b c column
# 1 a 100 300 300 85 c
# 2 b 200 304 104 304 b
# 3 c 300 100 100 500 a
# 4 d 400 405 405 405 <NA>
答案 2 :(得分:0)
您可以沿行应用功能,例如并使用结果填充列等
searchFunction <- function(row) {
result <- "NA"
for (name in names(row)) {
if (name == "target" || name == "id") {
next
}
if (result == "NA" && as.numeric(row[name]) < as.numeric(row["target"])) {
result = name
}
}
return(result);
}
apply(df, 1, searchFunction)
# [1] "c" "b" "a" "NA"