【问题标题】:R, Select first dataframe row for each unique pair, ignoring orderR,为每个唯一对选择第一个数据帧行,忽略顺序
【发布时间】:2016-07-31 19:13:26
【问题描述】:

围绕这个问题有很多问题,但我无法找到我特别关心的问题的答案。我有一个具有这种通用格式的数据框。

dat <- data.frame(V1 = c(1,1,2,1,2,4,5), V2 = c(1,2,1,2,1,5,4), V3 =    c('date1','date1','date2','date3','date4','date1','date2'))

dat
V1 V2    V3
1  1 date1
2  1 date1
1  2 date2
1  2 date3
2  1 date4
5  4 date1
4  5 date2

我想从第 1 列和第 2 列中找到唯一对(以便第 2、3、4、5 行都合并为一个唯一对),而不管顺序如何 (1, 2 = 2, 1)。我在 SO (Unique pairs in R, ignoring order) 上找到了这个不错的代码

colwise <- function(dat) data.frame(unique(cbind(pmin(dat[,1], dat[,2]), pmax(dat[,1], dat[,2]))))

这非常适合拉出第 1 列和第 2 列。

colwise(dat)
V1 V2
1  1
1  2
4  5

但是,我想找到唯一对(如上),但还包括每个唯一对的原始数据集中的整个第一行。在上面的示例中,最终输出将是

dat
V1 V2    V3
1  1 date1
1  2 date1
4  5 date1

在我的实际数据集中,我有更多的列和大约 100 万行,尽管只有 100-200 个真正唯一的列 1 和 2 组合。此外,唯一的对列实际上不是我的数据集中的第 1、2 列,所以指定特定列以测试唯一性的能力很重要。

对于如何修改 colwise 函数或如何使用生成的一组唯一对从原始数据帧中提取基于该唯一对的第一整行,是否有人有一些好的想法?

谢谢

【问题讨论】:

    标签: r


    【解决方案1】:

    dplyr 包中的 distinct 函数执行此操作。要忽略顺序,您可以先定义 smallerlarger 列,然后删除这些列:

    library(dplyr)
    dat %>%
      distinct(smaller = pmin(V1, V2),
               larger = pmax(V1, V2),
               .keep_all = TRUE) %>%
      select(-smaller, -larger)
    

    .keep_all 参数(从 dplyr 0.5 开始)告诉它不要丢弃其他(非 V1/V2)列。

    【讨论】:

    • 这是一个很棒的实现,而且速度非常快。比我以前使用的要快得多。我接受了@aichao 的回答,因为它展示了如何修改我的代码来解决我的问题,但是这个实现比我的实现要好。谢谢,很高兴看到 dplyr 的新应用
    【解决方案2】:

    使用duplicated 而不是unique 来获取唯一对而不是唯一对的重复索引,然后删除重复项:

    dat <- data.frame(V1 = c(1,1,2,1,2,4,5), V2 = c(1,2,1,2,1,5,4), V3 = c('date1','date1','date2','date3','date4','date1','date2'))
    
    dup <- function(dat) duplicated(cbind(pmin(dat[,1], dat[,2]), pmax(dat[,1], dat[,2])))
    
    print(dat[!dup(dat),])
    ##  V1 V2    V3
    ##1  1  1 date1
    ##2  1  2 date1
    ##6  4  5 date1
    

    请注意,这只会为您提供这些重复的唯一对中的第一个的整行,并且您说这就是您想要的。

    希望这会有所帮助。

    【讨论】:

    • 非常适合我需要的东西!我一直在研究如何合并重复,但没有意识到它会这么简单。
    【解决方案3】:

    您可以先对列进行排序,然后使用duplicated

    dat <- transform(dat, V1a=pmin(V1,V2), V2a=pmax(V1,V2))
    idx <- which(!duplicated(dat[,c("V1a", "V2a")]))
    dat <- dat[idx,]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 2017-08-08
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多