【问题标题】:Find duplicate rows in data frame based on multiple columns in r根据r中的多列查找数据框中的重复行
【发布时间】:2019-02-09 15:45:39
【问题描述】:

我有一个数据集,其中有一些实例,对于同一日期和时间的给定位置,值不同。我正在尝试创建一个显示这些实例的子集数据框。这是我的意思的一个例子:

我已经查看了关于 SO 的类似问题,但我似乎无法得到我想要的。我不断收到不是这种情况的实例。

这是我正在使用的代码:

dat1<-data_concern_join2%>%
 group_by(locid,stdate,sttime,charnam,valunit)%>%
  filter(n()>1) 

样本数据:

structure(list(orgid = c("USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ", 
"USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ", 
"USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ", "USGS-NJ"), locid = c("USGS-01396030", 
"USGS-01396030", "USGS-01389850", "USGS-01389850", "USGS-01391500", 
"USGS-01391500", "USGS-01391500", "USGS-01391500", "USGS-01393960", 
"USGS-01390610", "USGS-01391500", "USGS-01390610", "USGS-01391500", 
"USGS-01378760", "USGS-01378760"), stdate = structure(c(11359, 
11359, 11359, 11359, 16504, 16504, 16112, 16112, 11367, 13860, 
12401, 13860, 16325, 13006, 13006), class = "Date"), sttime = structure(c(34200, 
34200, 36000, 36000, 40500, 40500, 39600, 39600, 36000, 39600, 
32400, 39600, 38400, 36900, 36900), class = c("hms", "difftime"
), units = "secs"), charnam = c("Specific conductance", "Specific conductance", 
"Specific conductance", "Specific conductance", "Specific conductance", 
"Specific conductance", "Specific conductance", "Specific conductance", 
"Specific conductance", "Specific conductance", "Specific conductance", 
"Specific conductance", "Specific conductance", "Specific conductance", 
"Specific conductance"), val = c(7450, 7300, 3210, 3180, 1930, 
1920, 1740, 1650, 1480, 1390, 1380, 1330, 1300, 1280, 1270), 
    valunit = c("uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", 
    "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", 
    "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", 
    "uS/cm @25C"), swqs = c("FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT", 
    "FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT", 
    "FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT", "FW2-NT"), WMA = c(7L, 
    7L, 4L, 4L, 4L, 4L, 4L, 4L, 7L, 4L, 4L, 4L, 4L, 6L, 6L), 
    year = c(2001L, 2001L, 2001L, 2001L, 2015L, 2015L, 2014L, 
    2014L, 2001L, 2007L, 2003L, 2007L, 2014L, 2005L, 2005L), 
    HUC14 = c("HUC02030104050090", "HUC02030104050090", "HUC02030103120050", 
    "HUC02030103120050", "HUC02030103140070", "HUC02030103140070", 
    "HUC02030103140070", "HUC02030103140070", "HUC02030104050010", 
    "HUC02030103140010", "HUC02030103140070", "HUC02030103140010", 
    "HUC02030103140070", "HUC02030103010040", "HUC02030103010040"
    )), .Names = c("orgid", "locid", "stdate", "sttime", "charnam", 
"val", "valunit", "swqs", "WMA", "year", "HUC14"), row.names = c(NA, 
-15L), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), vars = c("locid", 
"stdate", "sttime", "charnam", "valunit"), drop = TRUE, indices = list(
    13:14, 2:3, c(9L, 11L), 10L, 6:7, 12L, 4:5, 8L, 0:1), group_sizes = c(2L, 
2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), biggest_group_size = 2L, labels = structure(list(
    locid = c("USGS-01378760", "USGS-01389850", "USGS-01390610", 
    "USGS-01391500", "USGS-01391500", "USGS-01391500", "USGS-01391500", 
    "USGS-01393960", "USGS-01396030"), stdate = structure(c(13006, 
    11359, 13860, 12401, 16112, 16325, 16504, 11367, 11359), class = "Date"), 
    sttime = structure(c(36900, 36000, 39600, 32400, 39600, 38400, 
    40500, 36000, 34200), class = c("hms", "difftime"), units = "secs"), 
    charnam = c("Specific conductance", "Specific conductance", 
    "Specific conductance", "Specific conductance", "Specific conductance", 
    "Specific conductance", "Specific conductance", "Specific conductance", 
    "Specific conductance"), valunit = c("uS/cm @25C", "uS/cm @25C", 
    "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", "uS/cm @25C", 
    "uS/cm @25C", "uS/cm @25C")), row.names = c(NA, -9L), class = "data.frame", vars = c("locid", 
"stdate", "sttime", "charnam", "valunit"), drop = TRUE, .Names = c("locid", 
"stdate", "sttime", "charnam", "valunit")))

【问题讨论】:

    标签: r dataframe dplyr duplicates


    【解决方案1】:

    这对你有用吗?

    dat1<-data_concern_join2%>%
     group_by(locid,stdate,sttime,charnam,valunit)%>%
      mutate(count = 1:n()) %>% # the number should increase with each replicated row
      filter(count == 1)  # filter only the first and remove the others
    

    输出:

    # A tibble: 9 x 12
    # Groups:   locid, stdate, sttime, charnam, valunit [9]
      orgid   locid         stdate     sttime charnam                val valunit    swqs     WMA  year HUC14             count
      <chr>   <chr>         <date>     <time> <chr>                <dbl> <chr>      <chr>  <int> <int> <chr>             <int>
    1 USGS-NJ USGS-01396030 2001-02-06 09:30  Specific conductance  7450 uS/cm @25C FW2-NT     7  2001 HUC02030104050090     1
    2 USGS-NJ USGS-01389850 2001-02-06 10:00  Specific conductance  3210 uS/cm @25C FW2-NT     4  2001 HUC02030103120050     1
    3 USGS-NJ USGS-01391500 2015-03-10 11:15  Specific conductance  1930 uS/cm @25C FW2-NT     4  2015 HUC02030103140070     1
    4 USGS-NJ USGS-01391500 2014-02-11 11:00  Specific conductance  1740 uS/cm @25C FW2-NT     4  2014 HUC02030103140070     1
    5 USGS-NJ USGS-01393960 2001-02-14 10:00  Specific conductance  1480 uS/cm @25C FW2-NT     7  2001 HUC02030104050010     1
    6 USGS-NJ USGS-01390610 2007-12-13 11:00  Specific conductance  1390 uS/cm @25C FW2-NT     4  2007 HUC02030103140010     1
    7 USGS-NJ USGS-01391500 2003-12-15 09:00  Specific conductance  1380 uS/cm @25C FW2-NT     4  2003 HUC02030103140070     1
    8 USGS-NJ USGS-01391500 2014-09-12 10:40  Specific conductance  1300 uS/cm @25C FW2-NT     4  2014 HUC02030103140070     1
    9 USGS-NJ USGS-01378760 2005-08-11 10:15  Specific conductance  1280 uS/cm @25C FW2-NT     6  2005 HUC02030103010040     1
    

    【讨论】:

    • 我仍然遇到不符合要求的实例。我只想要 locid、stdate、sttime、charnam、valunit 相同且 val 是唯一不同的列的实例。我希望数据框看起来像我在问题中添加的图像
    【解决方案2】:

    dplyrdistinct 就是为此而设计的

    data_concern_join2 %>% distinct(locid, stdate, sttime, charnam, valunit, .keep_all = T)
    

    【讨论】:

      【解决方案3】:

      我们可以的

      library(data.table)
      unique(setDT(data_concern_join2), 
             by = c('locid', 'stdate', 'sttime', 'charnam', 'valunit'))
      

      【讨论】:

      • 我仍然遇到不满足此要求的实例。我只想要 locid、stdate、sttime、charnam、valunit 相同且 val 是唯一不同的列的实例。
      • @KWANGER 根据描述,除非您的数据存在问题,否则代码应该可以工作。 filter(n() &gt; 1) 获取基于分组变量重复的行。如果不是这样,那就有问题了
      • 代码有效,但我仍然得到只有一次测量的实例。我想创建一个数据框,就像问题中添加的图像一样。 Where is 显示所有这些列都相同但值相同的两个实例。
      • @KWANGER 从您的 cmets 看来,好像是 data_concern_join2 %&gt;% group_by(locid, stdate, sttime, charnam, valunit) %&gt;% filter(n_distinct(val) == n())
      【解决方案4】:

      首先,关于删除一列中包含重复项的整行的简单问题:

      library(dplyr)
      
      df <- tibble(x=c(1,1:4), y=letters[1:5])
      
      df
      #> # A tibble: 5 x 2
      #>       x y    
      #>   <dbl> <chr>
      #> 1     1 a    
      #> 2     1 b    
      #> 3     2 c    
      #> 4     3 d    
      #> 5     4 e   
      
      df %>% 
        group_by(x) %>%
        mutate(rank=row_number(x)) %>%
        filter(rank==1)
        # optional: %>% ungroup() %>% select(-rank)
      #> # A tibble: 4 x 3
      #> # Groups:   x [4]
      #>       x y      rank
      #>   <dbl> <fct> <int>
      #> 1     1 a         1
      #> 2     2 c         1
      #> 3     3 d         1
      #> 4     4 e         1
      

      如果您的数据库支持窗口函数,这是 SQL 中的常见模式,但使用 dplyr 动词表示。这是 Redshift / PostgreSQL 表单:

      select * from df where 1 = row_number() over (partition by x)
      

      因此,如果您只想要重复项(x 重复的行),那么只需将 rank==1 替换为 rank&gt;1

      df %>% 
        group_by(x) %>%
        mutate(rank=row_number(x)) %>%
        filter(rank>1)
      
      #> # A tibble: 1 x 3
      #> # Groups:   x [1]
      #>       x y      rank
      #>   <dbl> <fct> <int>
      #> 1     1 b         2
      

      上面没有显示每个x 的原始行,只是它的重复项。如果您想要所有行,那么我认为其他答案涵盖了它,但我的版本是:

      x_dupes <- 
        df %>% 
        group_by(x) %>%
        summarise(n=n()) %>%
        filter(n>1) 
      
      df %>% semi_join(x_dupes, by = "x")
      
      #> # A tibble: 2 x 2
      #>       x y    
      #>   <dbl> <chr>
      #> 1     1 a    
      #> 2     1 b  
      

      最后,您可能还关心行的顺序,因为您可能对重复是什么有一个固定的看法。在此示例中,我将 y 的最后一个值按字母顺序保留,用于重复的 x

      df %>% 
        group_by(x) %>%
        arrange(desc(y)) %>%
        mutate(rank=row_number(x)) %>%
        filter(rank==1)
      
      #> # A tibble: 4 x 3
      #> # Groups:   x [4]
      #>       x y      rank
      #>   <dbl> <fct> <int>
      #> 1     4 e         1
      #> 2     3 d         1
      #> 3     2 c         1
      #> 4     1 b         1
      

      注意,与上面的第二个示例相比,y 在重复行中是 a,现在是 b。行顺序也颠倒了。

      【讨论】:

        猜你喜欢
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 2016-11-03
        • 2021-12-16
        • 1970-01-01
        相关资源
        最近更新 更多