【问题标题】:Conditional subset data frame based on value in multiple columns基于多列值的条件子集数据框
【发布时间】:2020-02-25 10:05:03
【问题描述】:

我有以下数据集(示例)

idnumber=c(12,12,13,14,14,15,16,17,18,18)
reg = c('FR','FR','DE','US','US','TZ','MK','GR','ES','ES')
code1=c('F56','G76','G56','T78','G78','G76','G64','T65','G79','G56')
code2=c('G56','I89','J83','S46','D78','G56','H89','G56','W34','T89')
df = data.frame(idnumber,reg,code1,code2)

给出:


  idnumber reg code1 code2
1   12     FR   F56   G56
2   12     FR   G76   I89
3   13     DE   G56   J83
4   14     US   T78   S46
5   14     US   G78   D78
6   15     TZ   G76   G56
7   16     MK   G64   H89
8   17     GR   T65   G56
9   18     ES   G79   W34
10  18     ES   G56   T89

我想对df 进行子集化,只保留值G56 出现在code1code 2 列中的原始值,但如果id 值与匹配的相同id 值则保留原始idnumberG56 如:


  idnumber reg code1 code2
1   12     FR   F56   G56
2   12     FR   G76   I89
3   13     DE   G56   J83
6   15     TZ   G76   G56
8   17     GR   T65   G56
9   18     ES   G79   W34
10  18     ES   G56   T89

我有数百万个观察结果和大约 30 个code 列。 希望问题足够清楚,欢迎任何建议!

干杯

【问题讨论】:

    标签: r dataframe subset


    【解决方案1】:

    这是一种方法:

    library(data.table)
    setDT(df)
    df[,.SD[any(code1 == 'G56' | code2 == 'G56')] ,.(idnumber)]
    
       idnumber reg code1 code2
    1:       12  FR   F56   G56
    2:       12  FR   G76   I89
    3:       13  DE   G56   J83
    4:       15  TZ   G76   G56
    5:       17  GR   T65   G56
    6:       18  ES   G79   W34
    7:       18  ES   G56   T89
    

    【讨论】:

      【解决方案2】:

      1.基地

      subset(df, idnumber %in% idnumber[code1=="G56" | code2=="G56"])
      

      2。 dplyr

      library(dplyr)
      
      df %>% filter(idnumber %in% idnumber[code1=="G56" | code2=="G56"])
      

      输出

      #   idnumber reg code1 code2
      # 1       12  FR   F56   G56
      # 2       12  FR   G76   I89
      # 3       13  DE   G56   J83
      # 4       15  TZ   G76   G56
      # 5       17  GR   T65   G56
      # 6       18  ES   G79   W34
      # 7       18  ES   G56   T89
      

      【讨论】:

        【解决方案3】:

        另一种基础 R 解决方案

        subset(df,`class<-`(ave(cbind(as.character(code1),as.character(code2)),
                              idnumber,
                              FUN = function(v) ifelse("G56"%in%v,TRUE,FALSE)),"logical")[,1])
        

        这样

           idnumber reg code1 code2
        1        12  FR   F56   G56
        2        12  FR   G76   I89
        3        13  DE   G56   J83
        6        15  TZ   G76   G56
        8        17  GR   T65   G56
        9        18  ES   G79   W34
        10       18  ES   G56   T89
        

        【讨论】:

          【解决方案4】:
          library(dplyr)
          df %>%
            semi_join(df %>%
            filter(code1=="G56" | code2=="G56"),by="idnumber")
          

            idnumber reg code1 code2
          1       12  FR   F56   G56
          2       12  FR   G76   I89
          3       13  DE   G56   J83
          4       15  TZ   G76   G56
          5       17  GR   T65   G56
          6       18  ES   G79   W34
          7       18  ES   G56   T89
          

          编辑:使用 30 个代码列可能会更简单:

          df %>%
            semi_join(df %>%
                        pivot_longer(cols=-c(idnumber, reg)) %>%
                        filter(value=="G56") %>%
                        pivot_wider(id_cols=c(idnumber, reg)),
                      by="idnumber")
          

          第三选择:

          df %>%
            semi_join(df %>%
                        filter_at(vars(starts_with("code")), any_vars(. == "G56")),
                      by="idnumber")
          

          编辑:如果“G56”在“代码”列中至少出现两次,OP 现在想要过滤记录(请参阅下面的评论)

          df %>%
            semi_join(df %>%
            mutate(n=rowSums(.[grep("code", names(.))] =="G56")) %>%
            group_by(idnumber) %>%
            filter(sum(n)>1),
            by="idnumber")
          
            idnumber reg code1 code2 code3
          1       12  FR   F56   G56   M56
          2       12  FR   G76   I89   G56
          3       18  ES   G79   W34   W33
          4       18  ES   G56   G56   T89
          

          数据:

          idnumber=c(12,12,13,14,14,15,16,17,18,18)
          reg = c('FR','FR','DE','US','US','TZ','MK','GR','ES','ES')
          code1=c('F56','G76','G56','T78','G78','G76','G64','T65','G79','G56')
          code2=c('G56','I89','J83','S46','D78','G56','H89','G56','W34','G56')
          code3=c('M56','G56','J83','S46','D78','G46','H89','J56','W33','T89')
          df = data.frame(idnumber,reg,code1,code2,code3)
          

          【讨论】:

          • 第三个选择是完美的!谢谢@Edward,但是如果我必须对“代码”列中值“G56”至少出现2次(即完整数据帧中的情况)的“idnumber”进行相同的过滤,该怎么办。无法弄清楚如何在公式中包含条件语句 => 2
          猜你喜欢
          • 2018-12-06
          • 2016-03-19
          • 1970-01-01
          • 2011-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多