选择适合某些逻辑测试的第一列的列名称

时间:2016-10-29 16:26:13

标签: r if-statement dataframe

我有以下输入:

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。 有没有人知道如何解决它?

3 个答案:

答案 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"