【问题标题】:Subset common rows from multiple data frames从多个数据框中子集公共行
【发布时间】:2018-01-04 22:58:07
【问题描述】:

我有多个数据框,如下所述,每行都有唯一的 ID。我正在尝试找到常见的行并创建一个至少出现在两个数据框中的新数据框。

id=2 的示例行出现在所有三个数据帧中。 df1 和 df3 中有类似的 Id= 3 行。

我想创建一个循环,它可以找到共同的行并创建一个具有共同行的新数据框。

df1 <- data.frame(Id=c(1,2,3,4),a=c(0,1,0,2),b=c(1,0,1,0),c=c(0,0,4,0)) 
df2 <- data.frame(Id=c(7,2,5,9),a=c(4,1,9,2),b=c(1,0,1,5),c=c(3,0,7,0))
df3 <- data.frame(Id=c(5,3,2,6),a=c(9,0,1,5),b=c(1,1,0,0),c=c(7,4,0,0)) 

> df1                   > df2 
 Id | a | b | c |         Id | a | b | c |
 ---|---|---|---|         ---|---|---|---|                  
  1 | 0 | 1 | 0 |          7 | 4 | 1 | 3 |                           
 ---|---|---|---|         ---|---|---|---|                  
  2 | 1 | 0 | 0 |          2 | 1 | 0 | 0 |
 ---|---|---|---|         ---|---|---|---|
  3 | 0 | 1 | 4 |          5 | 9 | 1 | 7 |
 ---|---|---|---|         ---|---|---|---|
  4 | 2 | 0 | 0 |          9 | 2 | 5 | 0 |

 > df3
 Id | a | b | c |
 ---|---|---|---|
  5 | 9 | 1 | 7 |
 ---|---|---|---|
  3 | 0 | 1 | 4 |
 ---|---|---|---|
  2 | 1 | 0 | 0 |
 ---|---|---|---|
  6 | 5 | 0 | 0 |

> expected_output
 Id | a | b | c |
 ---|---|---|---|
  5 | 9 | 1 | 7 |
 ---|---|---|---|
  3 | 0 | 1 | 4 |
 ---|---|---|---|
  2 | 1 | 0 | 0 |
 ---|---|---|---|

注意:- ID 是唯一的。 另外,我想从原始数据框中删除重复的行,并使用它来创建新的数据框。

【问题讨论】:

  • 同一张表中一行可以出现多次吗?

标签: r dataframe data.table dplyr tidyr


【解决方案1】:

合并所有数据框:

combined <- rbind(df1, df2, df3)

提取重复项:

duplicate_rows <- unique(combined[duplicated(combined), ])

duplicated(combined) 为您提供重复行的行索引)

【讨论】:

  • 我有超过 20 个数据框。我想到了这一点,但对于更多数据帧来说这不是一个好主意。
  • @RDP 数据帧是如何存储的?他们是在list,类似的名字等吗?
  • 如果您关心数据帧绑定效率,data.table 包中的rbindlist 函数可以非常有效地完成数据帧绑定。试试combined &lt;- rbindlist(list(df1, df2, df3))
  • 可以使用do.call(rbind, mget(ls(pattern = 'df[0-9]+')))制作初始数据框
【解决方案2】:

我有多个数据框,如下所述,每行都有唯一的 ID。我正在尝试找到常见的行并创建一个至少出现在两个数据框中的新数据框。

由于没有 ID 在同一个表中出现两次,我们可以将 ID 制成表格并将找到的任何 ID 保留两次:

library(data.table)

DTs = lapply(list(df1,df2,df3), data.table)

Id_keep = rbindlist(lapply(DTs, `[`, j = "Id"))[, .N, by=Id][N >= 2L, Id]

DT_keep = Reduce(funion, DTs)[Id %in% Id_keep]

#    Id a b c
# 1:  2 1 0 0
# 2:  3 0 1 4
# 3:  5 9 1 7

您的数据应该以DTs 之类的对象开头,而不是一堆单独的命名对象。

它是如何工作的

要了解它的工作原理,请检查像

这样的中间对象
  • list(df1,df2,df3)
  • lapply(DTs, `[`, j = "Id")
  • Reduce(funion, DTs)

另外,请阅读帮助文件,例如 ?lapply?rbindlist?funion

【讨论】:

  • 但是,它不会从原始 df 中删除重复的行。
  • @RDP 我不明白。您想更改输入表吗?我只看到上面的单个“expected_output”,所以正在创建它。或者你的意思是一个ID可以在输入表中出现两次(...这就是我问的原因)?
  • 是的,我想要新的预期输出。但是,也想删除常见的行
  • 啊,好吧,如果你问并且 Paolo 同意,你可以用它来编辑你的问题(因为我还没有看到它)。否则,您可以将其作为新问题发布。 Fwiw,我认为 lapply(DTs, fsetdiff, DT_keep) 可以解决问题..?
  • @RDP 好的。我认为好的礼仪是不要在问题中编辑新内容,除非每个发布答案的人都可以接受(所以,包括 Paolo)。 lapply(DTs, fsetdiff, DT_keep) 是你想要的吗?如果没有,也许您还需要为该部分问题显示所需的输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
相关资源
最近更新 更多