【问题标题】:R: removing rows and replacing values using conditions from multiple columnsR:使用多列中的条件删除行和替换值
【发布时间】:2011-06-09 18:40:37
【问题描述】:

我想过滤掉 var3

> foo <- data.frame(var1=c(1, 1, 8, 8, 5, 5, 5), var2=c(1,2,3,2,4,6,8), var3=c(7,1,1,1,1,1,6))
> foo
  var1 var2 var3
1    1    1    7
2    1    2    1
3    8    3    1
4    8    2    1
5    5    4    1
6    5    6    1
7    5    8    6

subset(foo, (foo$var3&gt;=5)) 将删除第 2 行到第 6 行,我会丢失 var1==8。

  • 如果 var1 的另一个值满足 foo$var3 >= 5 的条件,我想删除该行。请参见第 5 行。
  • 我想保留该行,如果值 var1 的所有出现不满足条件 foo$var3 >= 5,则将 NA 分配给 var2 和 var3。

这是我期望的结果:

  var1 var2 var3
1    1    1    7
3    8   NA   NA
7    5    8    6

这是我得到的最接近的:

> foo$var3[ foo$var3 < 5 ] = NA
> foo$var2[ is.na(foo$var3) ] = NA
> foo
  var1 var2 var3
1    1    1    7
2    1   NA   NA
3    8   NA   NA
4    8   NA   NA
5    5   NA   NA
6    5   NA   NA
7    5    8    6

现在我只需要知道如何有条件地删除正确的行(2、3 4、5、6):如果 var2 和 var3 为 NA 并且如果 var1 的值,则删除该行出现超过 1 次。

但肯定有一种更简单/优雅的方法来解决这个小问题。

编辑: 更改了 foo 以更类似于我的用例

【问题讨论】:

    标签: r


    【解决方案1】:

    最快的方法是使用合并:

    > merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,all.y=T)
      var1 var2 var3
    1    1    1    7
    2    5    8    6
    3    8   NA   NA
    

    unique(foo$var1) 给出 var1 中的唯一值。这些映射到 var3 大于 5 的数据帧。您取每个参数的第一列(all.x=1,all.y=1),然后说应该表示 y 中的所有值(all.y=T)。另见?merge

    如果你想保留订单,那么:

    > merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,
    + all.y=T)[order(unique(foo$var1)),]
      var1 var2 var3
    1    1    1    7
    3    8   NA   NA
    2    5    8    6
    

    merge 对发生映射的变量进行排序。 order 给出了这种排序,因此您可以使用该顺序作为索引来反转它。另见?order

    【讨论】:

      【解决方案2】:

      这是一种使用plyr 包函数ddplycolwise 以及subset 函数的方法。先定义一个辅助函数null2na

      null2na <- function(x) if ( length(x) == 0 ) NA else x
      

      接下来定义函数filter,我们希望将其应用于每个具有var1 特定值的子数据帧:

      filter <- function(df) cbind( data.frame( var1 = df[1,1]),
                                    colwise(null2na) (subset(df, var3 >= 5)[,-1]))
      

      现在通过var1foo 执行ddply

      > ddply(foo, .(var1), filter)
        var1 var2 var3
      1    1    1    7
      2    5    8    6
      3    8   NA   NA
      

      【讨论】:

        【解决方案3】:
        rbind(r <- subset(foo, (foo$var3>=5)), 
              unique(transform(subset(foo, !var1%in%r$var1), var2=NA, var3=NA)))
        

        一步一步:

        r <- subset(foo, (foo$var3>=5))
        
        r2 <- subset(foo, !var1%in%r$var1) # extract var1 != r$var1
        r3 <- transform(r2, var2=NA, var3=NA) # replace var2 and var3 with NA
        r4 <- unique(r3) # remove duplicates
        
        rbind(r, r4) # bind them
        

        【讨论】:

          【解决方案4】:

          完成后:

          foo$var3[ foo$var3 < 5 ] = NA
          foo$var2[ is.na(foo$var3) ] = NA
          

          您需要删除包含 NA 且也是 var1 重复值的行:

          foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]
          

          将此行视为识别包含 NA 值和重复 var1 值的行,然后选择其他所有值。

          编辑:如果数据框中的给定值 var1 的第一行的值是 var3 并且您要排除,我的解决方案不起作用。您需要先订购 data.frame 以确保完整的案例首先出现:

          foo <- foo[order(foo$var2),]   # ordering on var3 should be the same
          foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]
          

          【讨论】:

          • 使用更大的数据框,似乎并没有删除所有多余的 NA。
          • 那我不明白你的问题——你认为多余的 NA 是什么?这仅在 var1 的值重复时删除包含 NA 的行。如果 var1 中的值不重复,则该行将保留,无论它是否包含 NA。
          • 啊,我明白了。如果您首先按包含 NA 的列之一进行排序,我认为它可以解决问题: foo2
          【解决方案5】:

          试试这个:

          foo <- data.frame(var1= c(1, 1, 2, 3, 3, 4, 4, 5), 
               var2=c(9, 5, 13, 9, 12, 11, 13, 9), 
               var3=c(6, 8, 3, 6, 4, 7, 2, 9))
          f2=foo[which(foo$var3>5),]
          
          missing = which(!(foo$var1 %in% f2$var1))
          f3 = rbind(f2, list(foo$var1[missing], rep(NA, length(missing)),rep(NA,length(missing))))
          f3[order(f3$var1),]
          

          仅当您关心顺序时才需要最后一行(假设数据首先在 var1 上排序=。

          【讨论】:

          • 这适用于您答案中的数据框,但不适用于我的问题中更新的数据框。
          猜你喜欢
          • 2016-04-07
          • 1970-01-01
          • 1970-01-01
          • 2021-10-25
          • 2012-12-02
          • 1970-01-01
          • 1970-01-01
          • 2021-10-18
          • 2020-06-10
          相关资源
          最近更新 更多