【问题标题】:Remove rows if they have two labels如果行有两个标签,则删除它们
【发布时间】:2019-09-28 22:10:59
【问题描述】:

有一个数据框:

dframe <- structure(list(id = c(1L, 1L, 1L, 1L), name = c("Amazon", "Google", 
"Google", "Yahoo"), label = c("pre", "after", "pre", "after"), 
    text_sth = c("other", "another one test text_sth another text", 
    "another text other", "another one test text_sth another text"
    )), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-4L))

对于在每个名称中检测到的每个用户 ID,如何保留仅包含在列标签前后的行。预期输出示例:

 id name   label text_sth                                               
1 Google after another one test text_sth another text
1 Google pre   another text other  

【问题讨论】:

  • 请澄清“在每个名称中检测每个用户 ID”。您的示例数据中只有一个 id 值。

标签: r


【解决方案1】:

使用tidyverse,您可以将条件单独应用于数据框中的组。我们可以使用filter() 函数结合TRUE 在某些情况下被视为1 而FALSE 被视为零这一事实。 max() 函数在组内应用。

library(tidyverse)
dframe %>%
  group_by(id, name) %>%
  filter(max(label=="pre")==1, 
         max(label=="after")==1)

【讨论】:

    【解决方案2】:

    我们可以使用all 来检查组中是否存在所有必需的值

    library(dplyr)
    
    dframe %>%
      group_by(id, name) %>%
      filter(all(c("pre", "after") %in% label))
    
    #     id name   label text_sth                              
    #  <int> <chr>  <chr> <chr>                                 
    #1     1 Google after another one test text_sth another text
    #2     1 Google pre   another text other    
    

    我们可以在base R中实现同样的逻辑

    subset(dframe, as.logical(ave(label, id, name, FUN = function(x) 
                             all(c("pre", "after") %in% x))))  
    

    或者data.table中的两种方式

    library(data.table)
    setDT(dframe)
    dframe[dframe[, .I[all(c("pre", "after") %in% label)], by = .(id, name)]$V1]
    #OR
    dframe[, .SD[all(c("pre", "after") %in% label)], by = .(id, name)]
    

    【讨论】:

      【解决方案3】:

      我们可以使用

      library(dplyr)
      dframe %>%
        group_by(id, name) %>%
        filter(length(intersect(c("pre", "after"), label)) == 2)
      

      或者使用

      dframe %>%
          group_by(id, name) %>%
          filter(n_distinct(label) == 2)
      

      data.table

      library(data.table)
      setDT(dframe)[, .SD[length(intersect(c("pre", "after"), label)) ==2], 
                 .(id, name)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 2018-12-08
        • 1970-01-01
        • 1970-01-01
        • 2020-11-23
        • 2020-04-18
        • 1970-01-01
        相关资源
        最近更新 更多