【问题标题】:In R, Filter table based on column values in a other table?在R中,根据其他表中的列值过滤表?
【发布时间】:2016-02-08 20:34:06
【问题描述】:

我在这里搜索类似的问题,但找不到答案。请你能帮我完成这个任务。我有一张表,其中包含超过 10,000 名患者的大量患者记录数据集,而我还有一张仅包含 689 名患者的表。我想过滤大表以仅在第二个表中保留与患者相关的记录。然后创建一个将两个表分组的新表,这样我就得到了三个表(两个过滤表和一个合并表)。

============================= 我现在拥有的=============== ======

表 1(相关患者):

ID  |  PatientID  | Record1 |  Record2 |  Record3
--------------------------------------------------------
1   |  7366       |  3      |  1      |     1
2   |  7362       |  3      |  1      |     1
3   |  7361       |  3      |  1      |     1
4   |  7360       |  3      |  1      |     1
5   |  7363       |  3      |  1      |     1

表 2(所有患者):

   ID  |  PatientID  |  Blood      | SomeRecord |  Foo
    --------------------------------------------------------
    1   |  7316       |  06668      | 21/08/2015 |     1
    2   |  7302       |  08677      | 21/08/2015 |     3
    3   |  7341       |  07787      | 21/08/2015 |     2
    4   |  7340       |  08977      | 21/08/2015 |     1
    5   |  7313       |  07887      | 21/08/2015 |     1
    6   |  7366       |  56668      | 21/08/2015 |     1
    7   |  7362       |  88677      | 21/08/2015 |     3
    8   |  7361       |  77787      | 21/08/2015 |     2
    9   |  7360       |  98977      | 21/08/2015 |     1
    10  |  7363       |  87887      | 21/08/2015 |     1

我想根据表 1 的患者 ID 过滤表 2。将 1 和 2 组合到一个新表中。

============================= 期望输出================ =====

表 2(现在过滤的所有患者):

   ID  |  PatientID  |  Blood      | SomeRecord |  Foo
    --------------------------------------------------------
    6   |  7366       |  56668      | 21/08/2015 |     1
    7   |  7362       |  88677      | 21/08/2015 |     3
    8   |  7361       |  77787      | 21/08/2015 |     2
    9   |  7360       |  98977      | 21/08/2015 |     1
    10  |  7363       |  87887      | 21/08/2015 |     1

表 3(现在过滤所有患者并将所有记录分组):

   ID  |PatientID|Blood|SomeRecord|Foo|Record1|Record2|Record3
    --------------------------------------------------------
    6  |  7366   |56668|21/08/2015 |1 |   3   |    1   |  1    
    7  |  7362   |88677|21/08/2015 |3 |   3   |    1   |  1    
    8  |  7361   |77787|21/08/2015 |2 |   3   |    1   |  1    
    9  |  7360   |98977|21/08/2015 |1 |   3   |    1   |  1    
    10 |  7363   |87887|21/08/2015 |1 |   3   |    1   |  1    

【问题讨论】:

  • 我相信您正在寻找的词汇是反加入。
  • 我认为您想使用两个字段加入对吗? final_data<-merge(table2, table1, by =c("PatientID", "ID"), all.y = T)

标签: r filter group-by filtering grouping


【解决方案1】:

只需在dplyr 中加入两个连接:

library(dplyr)
semi_join(table2,table1, by=("PatientID"))
inner_join(table2,table1, by=("PatientID"))

结果:

> semi_join(table2,table1, by=("PatientID"))
  ID PatientID Blood SomeRecord Foo
1  6      7366 56668 21/08/2015   1
2  7      7362 88677 21/08/2015   3
3  8      7361 77787 21/08/2015   2
4  9      7360 98977 21/08/2015   1
5 10      7363 87887 21/08/2015   1
> inner_join(table2,table1, by=("PatientID"))
  ID.x PatientID Blood SomeRecord Foo ID.y Record1 Record2 Record3
1    6      7366 56668 21/08/2015   1    1       3       1       1
2    7      7362 88677 21/08/2015   3    2       3       1       1
3    8      7361 77787 21/08/2015   2    3       3       1       1
4    9      7360 98977 21/08/2015   1    4       3       1       1
5   10      7363 87887 21/08/2015   1    5       3       1       1

数据

table1 <-read.table(text="ID    PatientID   Record1   Record2   Record3
1     7366         3        1           1
2     7362         3        1           1
3     7361         3        1           1
4     7360         3        1           1
5     7363         3        1           1",
header=T,stringsAsFactors =F)

table2 <-read.table(text="  ID    PatientID    Blood       SomeRecord   Foo
    1     7316         06668       21/08/2015      1
    2     7302         08677       21/08/2015      3
    3     7341         07787       21/08/2015      2
    4     7340         08977       21/08/2015      1
    5     7313         07887       21/08/2015      1
    6     7366         56668       21/08/2015      1
    7     7362         88677       21/08/2015      3
    8     7361         77787       21/08/2015      2
    9     7360         98977       21/08/2015      1
    10    7363         87887       21/08/2015      1",
header=T,stringsAsFactors =F)

【讨论】:

  • 做了这个,但是表一有 613 行,表二有 6222 现在我使用了 inner_join 后,行数增加到 21046?你知道为什么吗?
  • right_join 不会工作。真的应该是inner_join
  • 我认为这是因为您有多个重复的 PatientID。
  • 我认为你真的想在两个字段“PatientID”和“ID”上进行子集化,这就是为什么你没有深入到 613 行。但我不能确定。
  • @SamanthaDS 不幸的是,添加“ID”将不起作用。患者 7366 的 ID 在表 1 中为 1,在表 2 中为 6。
【解决方案2】:

这是我在data.table 中的做法:

library(data.table)
setDT(table1) #convert each table _by reference_ to the data.table type
setDT(table2)

我实际上认为先完成第二步更容易。

一、反连接:

table3 <- table2[table1, on = "PatientID", nomatch = 0L]

我们可以将其视为一个子集,因为table1i 中;它同时是一个合并(通过使用on 来证明),即我们通过PatientID 合并table1table2,只保留在table1 中匹配的行(通过激活nomatch = 0 来删除不匹配的行行)

接下来,过滤table2

table2 <- table3[ ,names(table2), with = FALSE]

基本上,我们只是从table3 中删除table1 的所有列,以获得过滤后的table2

【讨论】:

    【解决方案3】:

    1) 没有包 如果 DF1 和 DF2 是两个 data.frame,那么 MM[1:5] 是必需的输出。如果不需要排序,请省略标记为 ## 的行:

    M <- merge(DF2, DF1[-1], by = "PatientID")
    
    o <- order(M$ID) ##
    M <- M[o, ] ##
    

    给予:

    > M[1:5]
    
      PatientID ID Blood SomeRecord Foo
    5      7366  6 56668 21/08/2015   1
    3      7362  7 88677 21/08/2015   3
    2      7361  8 77787 21/08/2015   2
    1      7360  9 98977 21/08/2015   1
    4      7363 10 87887 21/08/2015   1
    
    > M
      PatientID ID Blood SomeRecord Foo Record1 Record2 Record3
    5      7366  6 56668 21/08/2015   1       3       1       1
    3      7362  7 88677 21/08/2015   3       3       1       1
    2      7361  8 77787 21/08/2015   2       3       1       1
    1      7360  9 98977 21/08/2015   1       3       1       1
    4      7363 10 87887 21/08/2015   1       3       1       1
    

    2) sqldf

    > library(sqldf)
    > sqldf("select b.* from DF1 a join DF2 b using (PatientID)")
    
      ID PatientID Blood SomeRecord Foo
    1  6      7366 56668 21/08/2015   1
    2  7      7362 88677 21/08/2015   3
    3  8      7361 77787 21/08/2015   2
    4  9      7360 98977 21/08/2015   1
    5 10      7363 87887 21/08/2015   1
    
    > sqldf("select b.*, a.* from DF1 a join DF2 b using (PatientID)")
    
      ID PatientID Blood SomeRecord Foo ID PatientID Record1 Record2 Record3
    1  6      7366 56668 21/08/2015   1  1      7366       3       1       1
    2  7      7362 88677 21/08/2015   3  2      7362       3       1       1
    3  8      7361 77787 21/08/2015   2  3      7361       3       1       1
    4  9      7360 98977 21/08/2015   1  4      7360       3       1       1
    5 10      7363 87887 21/08/2015   1  5      7363       3       1       1
    

    注意:输入是:

    Lines1 <- "ID  |  PatientID  | Record1 |  Record2 |  Record3
    1   |  7366       |  3      |  1      |     1
    2   |  7362       |  3      |  1      |     1
    3   |  7361       |  3      |  1      |     1
    4   |  7360       |  3      |  1      |     1
    5   |  7363       |  3      |  1      |     1"
    
    Lines2 <- " ID  |  PatientID  |  Blood      | SomeRecord |  Foo
        1   |  7316       |  06668      | 21/08/2015 |     1
        2   |  7302       |  08677      | 21/08/2015 |     3
        3   |  7341       |  07787      | 21/08/2015 |     2
        4   |  7340       |  08977      | 21/08/2015 |     1
        5   |  7313       |  07887      | 21/08/2015 |     1
        6   |  7366       |  56668      | 21/08/2015 |     1
        7   |  7362       |  88677      | 21/08/2015 |     3
        8   |  7361       |  77787      | 21/08/2015 |     2
        9   |  7360       |  98977      | 21/08/2015 |     1
        10  |  7363       |  87887      | 21/08/2015 |     1"
    
    DF1 <- read.table(text = Lines1, header = TRUE, sep = "|", strip.white = TRUE)
    DF2 <- read.table(text = Lines2, header = TRUE, sep = "|", strip.white = TRUE)
    

    【讨论】:

      【解决方案4】:

      试试这个:

      final_data<-merge(table2, table1, by =c("PatientID", "ID"), all.y = T)
      

      【讨论】:

      • filtered_table2
      • 你为什么用data.table??几乎所有这些都是基本功能。
      • 您是否正在寻找有关 PaitentID 和 ID 的唯一记录?
      • 与“ID”不匹配,看起来像是观察记录,而不是唯一的患者标识符。 OP 很可能为它选择了一个坏名字。
      猜你喜欢
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 2014-07-26
      • 2021-04-05
      • 2015-10-10
      • 1970-01-01
      • 2022-12-21
      相关资源
      最近更新 更多