【问题标题】:Get the value and position of column based on a variable根据变量获取列的值和位置
【发布时间】:2016-01-02 12:21:14
【问题描述】:

这是复制我的数据集的代码。

col1=c(20,15,NA,NA)
col2=c(30,30,6,NA)
col3=c(40,NA,7,NA)
col4=c(NA,60,8,NA)
col5=c(60,75,9,NA)
check=c(40,35,10,NA)

df=data.frame(col1,col2,col3,col4,col5,check)

我想获取大于“检查”列的列的位置。如果可能,我也想获取该列的值。

这是我创建的一个函数,它不起作用:

fun=function(x){
        j1=which(x>df$check)[1]
        if(is.na(j1)){
                NA
        }
        else if (!is.na(j1)){
                j1
        }
}

df$test=apply(df[,1:5],1,fun)

我的最终数据框如下所示:

col1=c(20,15,NA,NA)
col2=c(30,30,6,NA)
col3=c(40,NA,7,NA)
col4=c(NA,60,8,NA)
col5=c(60,75,9,NA)
check=c(40,35,10,NA)
test=c(5,4,NA,NA)
value=c(60,60,NA,NA)
df=data.frame(col1,col2,col3,col4,col5,check, test,value)

任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: r function conditional apply


    【解决方案1】:

    我们可以使用max.col 来获取列索引。使用行序列和列索引,我们可以从前五列中提取元素。

    #created a logical matrix
    m1 <- df[1:5] > df$check
    #changed the NA elements to FALSE
    m1[is.na(m1)] <- FALSE
    #used max.col to get the column index.  For rows that have all FALSE
    #we change it to 0 after multiplying with the logical index of `rowSums(..`.
    v1 <- max.col(m1, 'first')*(rowSums(m1)!=0)
    #reconvert the 0 values to NA
    test <-  NA^(v1==0)*v1
    #extract the elements using row/column index
    value <- df[1:5][cbind(1:nrow(df), test)]
    #cbind the new vectors to get the desired output.
    df <- cbind(df, test, value)
    df
    #   col1 col2 col3 col4 col5 check test value
    #1   20   30   40   NA   60    40    5    60
    #2   15   30   NA   60   75    35    4    60
    #3   NA    6    7    8    9    10   NA    NA
    #4   NA   NA   NA   NA   NA    NA   NA    NA
    

    或者两个列都可以使用apply 创建。虽然这可能很紧凑,但与第一个解决方案相比,它的效率可能较低。我们使用applyMARGIN=1循环遍历行,获取大于第6个值的元素1到5的数字索引,子集第一次出现([1],如果没有元素,这将自动转换到NA)。基于这个索引,我们对元素进行子集化、连接、获取转置并分配给“df”中的新列。

    df[c('test', 'value')] <- t(apply(df, 1, function(x) {
                 i1 <- which(x[1:5]>x[6])[1]
                  c(i1, x[i1])}))
    

    【讨论】:

    • test 构造为max.col(m1, 'first')*NA^(rowSums(m1)==0) 使您免于处理中间变量。不过,也许更难解释。此外,最好将新的列添加到df 而不是cbind 新的列df[c("test","value")] &lt;- list(test,value)。要添加关于 apply 与 max.col 的评论吗?后者似乎在 SO 上更受欢迎。
    • @Frank 我曾想过在一行中使用它,但它变得有点难以理解。
    猜你喜欢
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    相关资源
    最近更新 更多