使用某些行值在R中形成组并检查以及从组

时间:2016-12-16 19:56:32

标签: r dataframe

假设我们有这样的数据框:

PatientID   BookingID   Level1   Level2  Value 
a1           101-A1        1     HBA1C   9.4
a2           102-A2        1     LDL     116
a1           101-A1        1     VLDL    11
a1           101-A1        2     POL     10
a1           102-A1        1     HBA1c   9.4
a2           102-A2        1     VLDL    10
a1           102-A1        1     VLDL    11
a2           103-A2        1     LDL     116
a2           103-A2        1     VLDL    11
a1           102-A1        2     POL     10

这个想法是,患者(唯一患者ID)可以来实验室并接受一系列条件的测试 - 更广泛的测试类别 level1 ,他们的子类别 level2 < / strong>(level1与level2有一对多的关系),现在患者ID的 BookingId 列可能因访问的不同日期而异。 列表示每项测试的值(患者ID与BookingID有一对多的关系)。

我想要一个输出:

PatientID   BookingID   Level1   Level2  Value 
a1           101-A1        1     HBA1C    9.4
a2           102-A2        1      LDL     116
a1           101-A1        1      VLDL    11
a1           101-A1        2      POL     10
a2           102-A2        1      VLDL    10
a2           103-A2        1      LDL     116
a2           103-A2        1      VLDL    11

我们基本上想要删除重复项,如果某项 - level1 测试,如果患者自己测试两次并且值保持相同,在上面的示例中 - 对于患者ID-a2,尽管具有相同的level1测试的值,只有VLDL值(最后一行输出 - 与第三个最后一个值不同)不同,因此a2保持不变,而a1的单独实例被删除。

现在假设这是一个非常大的数据集,我们必须对每个level1测试及其对应特定患者的值进行比较。

我试过了:final2 <- final1 %>% group_by(level1, patientId, value) %>% slice(1) 但显然它不会工作,并将删除一些不必要的行,因为它不是按照逻辑执行。请帮忙

2 个答案:

答案 0 :(得分:0)

final <- as.data.frame(sapply(final, toupper)) # consolidate case

final[!duplicated(dplyr::select(final, -BookingID), fromLast = T),]

      PatientID BookingID Level1 Level2 Value
         A1    102-A1      1  HBA1C   9.4
         A2    102-A2      1   VLDL    10
         A1    102-A1      1   VLDL    11
         A2    103-A2      1    LDL   116
         A2    103-A2      1   VLDL    11
         A1    102-A1      2    POL    10

答案 1 :(得分:0)

(小心)考虑以下......

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
( test_id INT NOT NULL 
, patient_id INT NOT NULL
,category_id INT NOT NULL
,value DECIMAL(6,2) NOT NULL
);

INSERT INTO my_table VALUES
( 1,1,101,9.4),
( 2,2,102,116),
( 3,1,103, 11),
( 4,1,104, 10),
( 5,1,101,9.4),
( 6,2,105, 10),
( 7,1,105, 11),
( 8,2,106,116),
( 9,2,105, 11),
(10,1,104, 10);

SELECT * FROM my_table;
+---------+------------+-------------+--------+
| test_id | patient_id | category_id | value  |
+---------+------------+-------------+--------+
|       1 |          1 |         101 |   9.40 |
|       2 |          2 |         102 | 116.00 |
|       3 |          1 |         103 |  11.00 |
|       4 |          1 |         104 |  10.00 |
|       5 |          1 |         101 |   9.40 |
|       6 |          2 |         105 |  10.00 |
|       7 |          1 |         105 |  11.00 |
|       8 |          2 |         106 | 116.00 |
|       9 |          2 |         105 |  11.00 |
|      10 |          1 |         104 |  10.00 |
+---------+------------+-------------+--------+

查询:

SELECT a.* 
  FROM my_table a 
  JOIN 
     ( SELECT MAX(test_id) test_id FROM my_table GROUP BY patient_id,category_id,value) b 
    ON b.test_id = a.test_id 
 ORDER 
    BY test_id;
+---------+------------+-------------+--------+
| test_id | patient_id | category_id | value  |
+---------+------------+-------------+--------+
|       2 |          2 |         102 | 116.00 |
|       3 |          1 |         103 |  11.00 |
|       5 |          1 |         101 |   9.40 |
|       6 |          2 |         105 |  10.00 |
|       7 |          1 |         105 |  11.00 |
|       8 |          2 |         106 | 116.00 |
|       9 |          2 |         105 |  11.00 |
|      10 |          1 |         104 |  10.00 |
+---------+------------+-------------+--------+

顺便提一下,&#39; booking_id&#39;可以即时生成,像这样......

SELECT a.test_id
     , a.patient_id
     , a.category_id
     , a.value
     , a.booking_id
  FROM 
     ( SELECT x.*
            , CONCAT_WS('-',x.patient_id,LPAD(CASE WHEN @prev = patient_id THEN @i:=@i+1 ELSE @i:=1 END,3,0)) booking_id
            , @prev:=patient_id 
         FROM my_table x
            , 
            ( SELECT @prev:=null,@i:=0) vars 
        ORDER 
           BY patient_id
            , test_id
     ) a
 ORDER 
    BY test_id;
+---------+------------+-------------+--------+------------+
| test_id | patient_id | category_id | value  | booking_id |
+---------+------------+-------------+--------+------------+
|       1 |          1 |         101 |   9.40 | 1-001      |
|       2 |          2 |         102 | 116.00 | 2-001      |
|       3 |          1 |         103 |  11.00 | 1-002      |
|       4 |          1 |         104 |  10.00 | 1-003      |
|       5 |          1 |         101 |   9.40 | 1-004      |
|       6 |          2 |         105 |  10.00 | 2-002      |
|       7 |          1 |         105 |  11.00 | 1-005      |
|       8 |          2 |         106 | 116.00 | 2-003      |
|       9 |          2 |         105 |  11.00 | 2-004      |
|      10 |          1 |         104 |  10.00 | 1-006      |
+---------+------------+-------------+--------+------------+