【问题标题】:Create a new variable based on value across columns根据跨列的值创建一个新变量
【发布时间】:2018-04-19 21:31:53
【问题描述】:

我有一个类似于以下简化版本的数据框:

MO1<-c("0","1","2","3")
MO2<-c("1","0","3","2")
MO3<-c("3","2","1","0")
df<-data.frame(MO1,MO2,MO3)
df

我正在尝试创建一个新变量,该变量将扫描所有 1 值的观察结果。然后,我希望这个新变量中的观察结果采用从中获得的列变量的名称,见下文:

MO1<-c("0","1","2","3")
MO2<-c("1","0","3","2")
MO3<-c("3","2","1","0")
MOTIVATION<-c("MO2","MO1","MO3","")
df2<-data.frame(MO1,MO2,MO3,MOTIVATION)
df2

抱歉,我不知道如何只显示生成的数据框 df2 从上面。

我的数据集中有 989 个观察值和 19 个不同的 MO.. 变量。

【问题讨论】:

    标签: r


    【解决方案1】:

    另一种选择

    > ind <- which(df==1, arr.ind = TRUE)
    > df2 <- df   # just cloning df
    > df2$MOTIVATION <- NA
    > df2$MOTIVATION[ind[,1]] <- names(df) [ind[,2]]
    > df2
      MO1 MO2 MO3 MOTIVATION
    1   0   1   3        MO2
    2   1   0   2        MO1
    3   2   3   1        MO3
    4   3   2   0       <NA>
    

    【讨论】:

      【解决方案2】:

      一种选择是将applywhich 结合使用:

      df$MOTIVATION <- apply(df,1,function(x)names(df)[which(x==1)])
      df
      #    MO1 MO2 MO3 MOTIVATION
      # 1   0   1   3        MO2
      # 2   1   0   2        MO1
      # 3   2   3   1        MO3
      # 4   3   2   0  
      

      【讨论】:

      • 感谢您的建议,有没有办法限制我可以查找 1 的数据框中的哪些列/变量?我还有其他列/变量中也有 1。当我运行您的脚本时,新变量具有所有具有 1 的列/变量的名称。
      【解决方案3】:

      1) 像这样试试max.col。在每一行前面插入一个 1,然后找到最后一个 1 的列。减去 1 使其与原始列号相对应,缺少的 1 为 0。然后用 NA 替换所有零并查找相应的列名。

      ix <- max.col(cbind(1, df) == 1, "last") - 1
      transform(df, MOTIVATION = names(df)[replace(ix, ix == 0, NA)])
      

      给予:

        MO1 MO2 MO3 MOTIVATION
      1   0   1   3        MO2
      2   1   0   2        MO1
      3   2   3   1        MO3
      4   3   2   0       <NA>
      

      2) 变体如下。我们计算max.col,然后如果该行中有 1,则将每个结果乘以 1,如果没有,则乘以 NA。

      df1 <- df == 1
      transform(df, MOTIVATION = names(df)[max.col(df1) * match(rowSums(df1), 1)])
      

      【讨论】:

        【解决方案4】:

        以下方法可以解决问题(请注意,这支持两列具有“1”的情况,不确定这是否对您来说是有效的边缘情况。 (我对原来的 MO4 稍作修改,使其包含两个“1”

        MO1<-c("0","1","2","3")
        MO2<-c("1","2","3","2")
        MO3<-c("3","2","1","0")
        MO4<-c("3","2","1","1")
        df<-data.frame(MO1,MO2,MO3,MO4)
        df
        
        
        findx <- function(dfx) 
        {
          idx <- which(dfx=="1")
          res <- lapply(idx, function(x) paste0('MO', x))
          res
        }
        
        found <- apply(df,2,findx)
        
        newdf <- unlist(found)
        newdf
        

        输出为

        “MO2”“MO1”“MO3”“MO3”“MO4”

        【讨论】:

          猜你喜欢
          • 2021-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-02
          相关资源
          最近更新 更多