【问题标题】:Removing specific rows from a dataframe从数据框中删除特定行
【发布时间】:2011-10-30 02:00:55
【问题描述】:

我有一个数据框,例如:

sub   day
1      1
1      2
1      3
1      4
2      1
2      2
2      3
2      4
3      1
3      2
3      3
3      4

我想删除可以通过 sub 和 day 的组合识别的特定行。 例如,假设我想删除 sub='1' 和 day='2' 和 sub=3 和 day='4' 的行。我怎么能这样做? 我意识到我可以指定行号,但这需要应用到一个巨大的数据框,这将是乏味的,并标识每一行。

【问题讨论】:

    标签: r dataframe rows


    【解决方案1】:

    这归结为两个不同的步骤:

    1. 找出您的条件何时为真,从而计算布尔向量,或者,我更喜欢通过将其包装到 which() 中来计算它们的索引
    2. 通过排除上一步中的索引来创建更新的data.frame

    这是一个例子:

    R> set.seed(42)
    R> DF <- data.frame(sub=rep(1:4, each=4), day=sample(1:4, 16, replace=TRUE))
    R> DF
       sub day
    1    1   4
    2    1   4
    3    1   2
    4    1   4
    5    2   3
    6    2   3
    7    2   3
    8    2   1
    9    3   3
    10   3   3
    11   3   2
    12   3   3
    13   4   4
    14   4   2
    15   4   2
    16   4   4
    R> ind <- which(with( DF, sub==2 & day==3 ))
    R> ind
    [1] 5 6 7
    R> DF <- DF[ -ind, ]
    R> table(DF)
       day
    sub 1 2 3 4
      1 0 1 0 3
      2 1 0 0 0
      3 0 1 3 0
      4 0 2 0 2
    R> 
    

    我们看到sub==2 只剩下一个与day==1 相关的条目。

    编辑复合条件可以用“或”来完成,如下所示:

    ind <- which(with( DF, (sub==1 & day==2) | (sub=3 & day=4) ))
    

    这是一个新的完整示例

    R> set.seed(1)
    R> DF <- data.frame(sub=rep(1:4, each=5), day=sample(1:4, 20, replace=TRUE))
    R> table(DF)
       day
    sub 1 2 3 4
      1 1 2 1 1
      2 1 0 2 2
      3 2 1 1 1
      4 0 2 1 2
    R> ind <- which(with( DF, (sub==1 & day==2) | (sub==3 & day==4) ))
    R> ind
    [1]  1  2 15
    R> DF <- DF[-ind, ]
    R> table(DF)
       day
    sub 1 2 3 4
      1 1 0 1 1
      2 1 0 2 2
      3 2 1 1 0
      4 0 2 1 2
    R> 
    

    【讨论】:

    • 好的,我认为这需要一些额外的帮助......我需要确定多天,所以我尝试稍微修改你的代码:ind
    • 使用表达式来计算独立,您可能会发现help(match) 很有用。
    • 这个答案对所需的策略、如何应用代码、应用什么代码进行了解释,并附有示例。这很有帮助。
    • ind 为空似乎有问题:结果是空子集而不是完整集 (DF)。
    【解决方案2】:
    DF[ ! ( ( DF$sub ==1 & DF$day==2) | ( DF$sub ==3 & DF$day==4) ) , ]   # note the ! (negation)
    

    或者如果 sub 是您使用引号所建议的一个因素:

    DF[ ! paste(sub,day,sep="_") %in% c("1_2", "3_4"), ]
    

    也可以使用子集:

    subset(DF,  ! paste(sub,day,sep="_") %in% c("1_2", "3_4") )
    

    (并且我赞同在使用“[”时在 Dirk 的回答中使用 which,即使有些人声称不需要它。)

    【讨论】:

    • 这就是票。谢谢。 %in% 是什么意思?
    • 这是一个中缀运算符的示例,它返回一个逻辑向量,告诉您第一个参数中的哪些元素包含在第二个参数中。请参阅 ?match 它的定义位置。
    • @BondedDust 和这里
    • @42:当它根本不考虑day时,我不明白为什么这是问题的答案。
    • @U.Windl 我(代表 BondedDust 和我自己)同意。已编辑。
    【解决方案3】:

    这是使用dplyrfilter 函数解决您的问题的方法。

    虽然您可以将您的数据框作为第一个参数传递给任何 dplyr 函数,但我使用了它的 %&gt;% 运算符,它将您的数据框通过管道传递给一个或多个 dplyr 函数(在这种情况下只需过滤)。

    一旦您对 dplyr 有点熟悉,cheat sheet 就非常方便。

    > print(df <- data.frame(sub=rep(1:3, each=4), day=1:4))
       sub day
    1    1   1
    2    1   2
    3    1   3
    4    1   4
    5    2   1
    6    2   2
    7    2   3
    8    2   4
    9    3   1
    10   3   2
    11   3   3
    12   3   4
    > print(df <- df %>% filter(!((sub==1 & day==2) | (sub==3 & day==4))))
       sub day
    1    1   1
    2    1   3
    3    1   4
    4    2   1
    5    2   2
    6    2   3
    7    2   4
    8    3   1
    9    3   2
    10   3   3
    

    【讨论】:

      【解决方案4】:

      一个简单的解决方案:

      cond1 &lt;- df$sub == 1 &amp; df$day == 2

      cond2 &lt;- df$sub == 3 &amp; df$day == 4

      df &lt;- df[!(cond1 | cond2),]

      【讨论】:

        猜你喜欢
        • 2012-01-04
        • 2017-08-17
        • 1970-01-01
        • 2015-10-15
        • 1970-01-01
        • 1970-01-01
        • 2018-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多