【问题标题】:How to remove duplicate rows in both using a condition in R [duplicate]如何使用R中的条件删除两者中的重复行[重复]
【发布时间】:2016-08-16 13:38:35
【问题描述】:

我的数据是这样的:

RES1 <- c("A","B","A","A","B")
RES2 <- c("B","A","A","B","A")
VAL1 <-c(3,5,3,6,8)
VAL2 <- c(5,3,7,2,7)
dff <- data.frame(RES1,VAL1,RES2,VAL2)
dff
  RES1 VAL1 RES2 VAL2
  1    A    3    B    5 
  2    B    5    A    3
  3    A    3    A    7
  4    A    6    B    2
  5    B    8    A    7

我想删除我已经拥有相同 res1-res2 对的行。例如:A 3 与 B 5 交互。这就是我想要的信息。我不在乎哪一对是第一个。 B 5 与 A 3 或 A 3 与 B 5。我想要得到的是以下数据框:

output
  RES1 VAL1 RES2 VAL2
   1    A    3    B    5
   2    A    3    A    7
   3    A    6    B    2
   4    B    8    A    7

然后我想对另一个数据框做同样的事情,例如:

RES3 <- c("B","B","B","A","B")
RES4 <- c("A","A","A","A","B")
VAL4 <- c(3,7,5,3,8)
VAL3 <- c(5,8,3,7,3)
df2 <- data.frame(RES3,VAL3,RES4,VAL4)

df2
  RES3 VAL3 RES4 VAL4
   1     B     5     A     3
   2     B     8     A     7
   3     B     3     A     5
   4     A     7     A     3
   5     B     3     B     8

最后,我只想保持相互对(在我的定义中,两对是相同的,保持一对是必不可少的:“A 5”-“B 3”与“B 3”-“A 5”相同"。换句话说,顺序无关紧要。

我希望的最终输出应该有以下对,它们是唯一的,并且存在于两个数据帧中:

mutualpairs
  RESA VALA RESB VALB
  A     3     B     5
  A     3     A     7
  B     8     A     7

【问题讨论】:

  • Related: stackoverflow.com/q/25297812 也许值得注意的是 pmax/pmin 比 rowwise sort 快得多。
  • @digEmAll 我已经编辑了问题,仍然可以使用您的帮助。
  • 好的,从一个 data.frame 移动到两个是一个相当大的变化(足以使当前的答案不再有效)。也许您应该改为发布一个新问题。不过,如果你愿意,我会找人重新提出这个问题。 (我自己做不到。)不确定 digEmAll 是否被 ping 通。您可能应该在他的回答下发表评论,而不是在这里。
  • @Frank 我想我会打开一个新问题并删除这个问题。这行得通吗?
  • 您将无法删除这个,因为它有一个赞成的答案。 (你也不应该,因为原则上它可能对其他人有用。)但我认为打开另一个很好。我的建议是:让新帖子自成一体;链接在这里,但要确保它本身是可以理解的。

标签: r dataframe comparison remove-if


【解决方案1】:

您可以使用此代码:

dff[!duplicated(t(apply(cbind(paste(dff$RES1,dff$VAL1),paste(dff$RES2,dff$VAL2)),1,sort))),]

等效的展开代码:

v1 <- paste(dff$RES1,dff$VAL1)
v2 <- paste(dff$RES2,dff$VAL2)
mx <- cbind(v1,v2)
mxSorted <- t(apply(mx,1,sort))
duped <- duplicated(mxSorted)
dff[!duped,]

解释:

1) 我们通过连接列 RES1-VAL1 和 RES2-VAL2 来创建两个字符向量 v1v2(请注意,paste 使用空格作为默认分隔符,也许您可​​以使用另一个字符或字符串作为更安全(例如|@; 等...)
结果:

> v1
[1] "A 3" "B 5" "A 3" "A 6" "B 8"
> v2
[1] "B 5" "A 3" "A 7" "B 2" "A 7"

2) 我们使用cbind 将这两个向量绑定成一个矩阵;
结果:

     [,1]  [,2] 
[1,] "A 3" "B 5"
[2,] "B 5" "A 3"
[3,] "A 3" "A 7"
[4,] "A 6" "B 2"
[5,] "B 8" "A 7"

3) 我们使用t(apply(mx,1,sort))对矩阵每一行的值进行排序;
通过对行进行排序,我们只需使刚刚交换的具有相同值的行完全相同(请注意,最终转置是必要的,因为apply 函数总是返回列上的结果)。
结果:

     [,1]  [,2] 
[1,] "A 3" "B 5"
[2,] "A 3" "B 5"
[3,] "A 3" "A 7"
[4,] "A 6" "B 2"
[5,] "A 7" "B 8"

4) 在矩阵上调用duplicated,我们得到一个长度 = nrow(matrix) 的逻辑向量,如果一行是前一行的副本,则为 TRUE,所以在我们的例子中,我们得到:

[1] FALSE  TRUE FALSE FALSE FALSE
# i.e. the second row is a duplicate

5)最后我们用这个向量过滤data.frame的行,得到最终结果:

  RES1 VAL1 RES2 VAL2
1    A    3    B    5
3    A    3    A    7
4    A    6    B    2
5    B    8    A    7

【讨论】:

    【解决方案2】:

    Remove duplicates column combinations from a dataframe in R 可能重复

    在这里调整答案:

    dff[!duplicated(dff[c('RES1','RES2')]),]
    

    【讨论】:

    • 这几乎就是我想要的。但是这一行的结果是我的输出数据帧的第 1、3 和 4 行。但是,我也想要第二行。条件 'RES1', 'VAL1' 不是我想要的。我想消除 RES1 和 RES2 交替出现的那些,例如 dff 数据帧中的第 1 行和第 2 行。
    • 您为dff 提供的数据似乎有误。但是,我意识到您想消除基于 RES1、RES2 而不是 RES1、VAL1 的重复项,并相应地编辑了答案。
    • 不。我想保留一对原始的 RES 和 VAL。例如,如果我有 A 3 B 5,我不想保留 B 5 A 3,因为它只是另一个的交换版本。 A 3 与 B 5 交互。这就是我想要的信息。我不在乎哪一对是第一个。 B 5 和 A 3 或 A 3 和 B 5。所以 res1,res2 也没有给我正确的答案。
    • @wthimdh 所以也许你需要dff[!duplicated(t(apply(dff, 1, sort))), ]
    • @wthimdh:你是说我的代码吗?它有效,复制/粘贴时请注意,因为它跨越多行,所以它也会复制一些奇怪的字符;)
    猜你喜欢
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 2019-09-23
    相关资源
    最近更新 更多