代码之家  ›  专栏  ›  技术社区  ›  s__

r基于分层数据中的子删除父行

  •  0
  • s__  · 技术社区  · 6 年前

    我正在处理这样的数据:

    id <- c(1,1,1,2,2,2,3,3,3,4,4)                         # fathers
    name <- c('a','b','k','b','e','g','e','f','k','f','u') # sons
    data <- data.frame(id,name)
    data
    
       > data
        id name
    1   1    a
    2   1    b
    3   1    k
    4   2    b
    5   2    e
    6   2    g
    7   3    e
    8   3    f
    9   3    k
    10  4    f
    11  4    u
    

    我的目标是这样的:如果只有一个我不想要的儿子,那就把所有和不喜欢的儿子的父亲在一起的争吵都除掉。例如,我不喜欢儿子 e ,结果应该是:

    > data_e
        id name
    1   1    a
    2   1    b
    3   1    k
    # 4   2    b
    # 5   2    e
    # 6   2    g
    # 7   3    e
    # 8   3    f
    # 9   3    k
    10  4    f
    11  4    u
    

    因为id为2和3的行的名称是e。
    这也可能是一个类似“我不喜欢”的任务 e f “一起”:

        > data_eandf
        id name
    1   1    a
    2   1    b
    3   1    k
    4   2    b
    5   2    e
    6   2    g
    # 7   3    e
    # 8   3    f
    # 9   3    k
    10  4    f
    11  4    u
    

    或者,“如果你有 e f “:

    > data_eorf
        id name
    1   1    a
    2   1    b
    3   1    k
    # 4   2    b
    # 5   2    e
    # 6   2    g
    # 7   3    e
    # 8   3    f
    # 9   3    k
    # 10  4    f
    # 11  4    u
    

    如您所注意到的,更清楚地说,我已经“评论”了必须删除的行。

    我已经搜索过了,但是我发现很多问题都是基于一个列,比如 data[which(data$name=='e'),] ,但这只会在儿子的级别上删除,而不会删除所有相关父亲的行。

    此外,我还考虑过将数据放在宽格式中,将id的所有名称粘贴到一个唯一的单元格中,并在例如 grepl() ,但我认为这可能是大型数据集的问题(这些数据是一个示例)。

    你知道怎么处理这件事吗?
    提前谢谢

    3 回复  |  直到 6 年前
        1
  •  2
  •   CPak    6 年前

    这里有一个函数来处理不同的情况

    dislike1 <- c('e')
    dislike2 <- c('e', 'f')
    
    myfun <- function(df, dislike, ops = NULL) {
        require(dplyr)
        if (is.null(ops) || ops == 'OR') {
            df %>%
                group_by(id) %>%
                filter(!any(name %in% dislike)) %>%
                ungroup
        } else if (ops == 'AND') {
            df %>%
                group_by(id) %>%
                filter(!all(dislike %in% name)) %>%
                ungroup
        }
    }
    
    myfun(data, dislike1)
    # A tibble: 5 x 2
         # id name 
      # <dbl> <fct>
    # 1     1 a    
    # 2     1 b    
    # 3     1 k    
    # 4     4 f    
    # 5     4 u    
    myfun(data, dislike2, 'AND')
    # A tibble: 8 x 2
         # id name 
      # <dbl> <fct>
    # 1     1 a    
    # 2     1 b    
    # 3     1 k    
    # 4     2 b    
    # 5     2 e    
    # 6     2 g    
    # 7     4 f    
    # 8     4 u    
    myfun(data, dislike2, 'OR')
    # A tibble: 3 x 2
         # id name 
      # <dbl> <fct>
    # 1     1 a    
    # 2     1 b    
    # 3     1 k    
    
        2
  •  1
  •   Eric Yang    6 年前
    data[!(data$id %in% unique(data[data$name == 'e', 'id'])),]
    

    unique(data[data$name=='e','id'])将获得在name字段中具有'e'的唯一id。然后,您可以使用%in%运算符查找具有这些ID的所有行。是一个否定运算符。

        3
  •  0
  •   moooh    6 年前

    我有一个data.table解决方案

    require(data.table)
    
    id <- c(1,1,1,2,2,2,3,3,3,4,4)                         # fathers
    name <- c('a','b','k','b','e','g','e','f','k','f','u') # sons
    data <- data.table(id,name)
    
    # names to be deleted
    to_del <- c("e","f")
    
    # returns only id's without any of the names to be deleted
    data[ , .SD[ !any(name %in% to_del) ,name ] , by = "id"]
    
       id V1
    1:  1  a
    2:  1  b
    3:  1  k