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

Nil*_*ils 2 if-statement r 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))
Run Code Online (Sandbox Code Playgroud)

我想添加一个新列"列",表示每行,列"a","b","c"中的哪一列是第一列,其值小于目标解决方案.请求的输出如下所示:

要求输出:

df$column <- c("c", "b", "a", "NA")
df
Run Code Online (Sandbox Code Playgroud)

我考虑了如果每行检查一个浓缩,并使用apply函数将其应用于所有行.但是abc列很长(第20轮,因此需要一个循环),行数约为4.000.有没有人知道如何解决它?

Jaa*_*aap 5

你可以这样做:

1)创建一个逻辑矩阵,指示"a","b"或"c"列中的值是否小于目标列:

m <- df[,3:5] < df[,2]
Run Code Online (Sandbox Code Playgroud)

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)]]
Run Code Online (Sandbox Code Playgroud)

3)将名称分配给新列:

df$column <- names(df[,3:5])[mc]
Run Code Online (Sandbox Code Playgroud)

这使:

> 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>
Run Code Online (Sandbox Code Playgroud)

我将这些步骤分开,以使代码更清晰.但是你当然可以更好地整合它,如下所示:

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)]]]
Run Code Online (Sandbox Code Playgroud)