如何删除R中由三列组成的组中的重复项

如何删除R中由三列组成的组中的重复项,r,dataframe,dplyr,unique,R,Dataframe,Dplyr,Unique,假设我们有这样一个数据帧: 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

假设我们有这样一个数据帧:

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
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
library(dplyr)
library(stringr)
library(tidyr)
df %>% 
  group_by(PatientID, BookingID) %>% 
  mutate(Key = paste(Level1, Level2, Value, collapse=";")) %>% 
  ungroup() %>% 
  select(-Level1, -Level2, -Value) %>% 
  distinct(PatientID, Key, .keep_all=TRUE) %>% 
  mutate(Key = str_split(Key, ";")) %>% 
  unnest(Key) %>% 
  separate(Key, into=c("Level1", "Level2", "Value"), 
           sep=" ", remove=TRUE) %>%
  arrange(PatientID, BookingID, Level1, Level2)

# A tibble: 7 × 5
  PatientID BookingID Level1 Level2 Value
*     <chr>     <chr>  <chr>  <chr> <chr>
1        a1    101-A1      1  HBA1C   9.4
2        a1    101-A1      1   VLDL    11
3        a1    101-A1      2    POL    10
4        a2    102-A2      1    LDL   116
5        a2    102-A2      1   VLDL    10
6        a2    103-A2      1    LDL   116
7        a2    103-A2      1   VLDL    11
其想法是,患者(唯一的患者ID)可以来到实验室并接受一组条件的测试-更广泛的测试类别是level1,其子类别是level2(level1与level2有一对多关系),现在患者ID的BookingId列可以根据不同的就诊日期而有所不同。值列表示每个测试的值(患者ID与BookingID具有一对多关系)

因此,一组由“级别1”、“patientID”及其“值”的一个组合组成,如果patientIDa1两次来测试自己——101-a1和102-a1,并且如果所有测试值都相同,则只剩下其中一个,如果有任何变化,如patientIDa2的情况,则所有值都保留,因此,我们希望o/p如下所示:

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
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
library(dplyr)
library(stringr)
library(tidyr)
df %>% 
  group_by(PatientID, BookingID) %>% 
  mutate(Key = paste(Level1, Level2, Value, collapse=";")) %>% 
  ungroup() %>% 
  select(-Level1, -Level2, -Value) %>% 
  distinct(PatientID, Key, .keep_all=TRUE) %>% 
  mutate(Key = str_split(Key, ";")) %>% 
  unnest(Key) %>% 
  separate(Key, into=c("Level1", "Level2", "Value"), 
           sep=" ", remove=TRUE) %>%
  arrange(PatientID, BookingID, Level1, Level2)

# A tibble: 7 × 5
  PatientID BookingID Level1 Level2 Value
*     <chr>     <chr>  <chr>  <chr> <chr>
1        a1    101-A1      1  HBA1C   9.4
2        a1    101-A1      1   VLDL    11
3        a1    101-A1      2    POL    10
4        a2    102-A2      1    LDL   116
5        a2    102-A2      1   VLDL    10
6        a2    103-A2      1    LDL   116
7        a2    103-A2      1   VLDL    11
我尝试使用Dplyr包中的以下代码,但这会删除我们想要的内容:

abcTest1 <- FullData %>% group_by(level1, patientId, value) %>% slice(1)
abcTest1%group\u by(level1,patientId,value)%%>%slice(1)

我似乎无法正确执行此操作,请提供输入

使用优秀的软件包以简单的方式执行此操作:

install.packages(“data.table”)
库(数据表)
FullData%%as.data.table
abcTest1%唯一性(由=c(“级别1”、“患者ID”、“值”))

这是
duplicated()
函数的经典用法。此函数用于确定向量或数据帧的唯一元素,并返回一个逻辑值,该值指示在对象中较早看到的元素。在这种情况下,我们可以对要查找其唯一元素的数据帧列使用
duplicated()
,并使用输出进行索引

> df[!duplicated(df[c("PatientID", "Level1", "Value")]), ]
  PatientID BookingID Level1 Level2 Value
1        a1    101-A1      1  HBA1C   9.4
2        a2    102-A2      1    LDL 116.0
3        a1    101-A1      1   VLDL  11.0
4        a1    101-A1      2    POL  10.0
6        a2    102-A2      1   VLDL  10.0
9        a2    103-A2      1   VLDL  11.0

我的输出与您的略有不同,因为第二行的值
116
不在那里,但根据您的描述,我认为这是示例中的一个错误。

您只需使用unique

PatientID <- c("a1","a2","a1")
BookingID <- c("num1","num2","num1")
Level1 <- c(1,2,1)
Level2 <- c("HBA", "CDA", "HBA")
Value <- c(10,4,10)

df <- data.frame(PatientID,BookingID,Level1,Level2,Value)
df <- unique(df)

PatientID您也可以这样做:

library(dplyr)
> df
# A tibble: 10 × 5
   PatientID BookingID Level1 Level2 Value
       <chr>     <chr>  <dbl>  <chr> <dbl>
1         a1    101-A1      1  HBA1C   9.4
2         a2    102-A2      1    LDL 116.0
3         a1    101-A1      1   VLDL  11.0
4         a1    101-A1      2    POL  10.0
5         a1    102-A1      1  HBA1c   9.4
6         a2    102-A2      1   VLDL  10.0
7         a1    102-A1      1   VLDL  11.0
8         a2    103-A2      1    LDL 116.0
9         a2    103-A2      1   VLDL  11.0
10        a1    102-A1      2    POL  10.0
> df %>% distinct(PatientID, Level1, Value, .keep_all=TRUE)
# A tibble: 6 × 5
  PatientID BookingID Level1 Level2 Value
      <chr>     <chr>  <dbl>  <chr> <dbl>
1        a1    101-A1      1  HBA1C   9.4
2        a2    102-A2      1    LDL 116.0
3        a1    101-A1      1   VLDL  11.0
4        a1    101-A1      2    POL  10.0
5        a2    102-A2      1   VLDL  10.0
6        a2    103-A2      1   VLDL  11.0

基本上,我们首先从我们最感兴趣的三个值开始,
Level1
Level2
、和
Value
,然后放入一个字符串,在该字符串中,我们用分号分隔每个
BookingID
的每组值。这将为我们提供两行信息,分别是
PatientID==a1
PatientID==a2
,总共四行。然后,我们仅通过
PatientID
Key
进行重复数据消除,但同时告诉R保留
BookingID
。我们发现
a1
的数据相同,但
a2
的数据不同,因为
Value
其中
Level2==POL
在两次就诊中不相同。因此,在重复数据消除之后,剩下三行。然后,我们使用分号作为分隔符拆分
Key
,然后
separate
Key
变量以恢复原始列。

我可以问一下,您为什么要在您的问题中添加标签
mysql
excel
sqlite
?这个问题似乎与其中任何一个都无关。我可能选择了
unique
subset
dataframe
。@Barker我可以选择在任何工具上执行此操作,因为sqldf Package支持sql语法请不要麻烦使用一致的列名称。无论如何,这个函数的dplyr函数是
DF%>%distinct(Level1,PatientID,Value)
我认为这不起作用,因为
unique()
将查看所有列,而
BookingID
Level2
列将导致问题。Barker,但问题要求它在所有列中都是唯一的,不是吗?巴克,这会导致什么样的问题,你能运行我的代码一次并检查一下吗?它是根据询问者的要求重新生成的“一组由“级别1”、“patientID”及其“值”的一个组合组成,如果patientID a1两次参加测试——101-a1和102-a1,并且如果所有测试值相同,则只剩下其中一个,因此只有
Level1
PatientID
Value
重要,而不是
BookingID
Level2
。您的示例之所以有效,是因为您在不同的数据上使用它。我在询问者的数据上运行了它,没有删除任何内容。您可以使用
read.table(text=“copyAndPasteTextHere”,header=TRUE)
轻松读取他们的数据。@Barker您可以提出其他建议吗?请正确理解问题-patientID a2在最后一列“11”中有一个不同的vldl值,因此,该patientID的特定级别1的所有其他值需要保持不变,因此使用值为116的第二行needed@Rohan你想要的是;如果
PatientID
Level1
的所有唯一组合具有相同的
,则返回
PatientID
Level1
的唯一值;否则返回该
PatientID
的所有数据?是的,这个想法是如果一名患者来进行三次1级测试-假设1级有20个不同的测试(由2级显示),那么如果在所有20*3条目中,前20个值重复3次,那么我们取唯一的值,否则即使有一个不匹配,我们保留所有信息,因为这一步的问题是,如果有一个非常大的数据集…那么可能会发生这样的情况,即使整个二级测试的一级值可能不同-但如果一些二级值相同,这些值将被删除-尽管它们将处于相同的一级。哇,添加库(magrittr)abcTest1%唯一性(by=(“level1”,“patientId”,“value”))错误:意外”,“in”abcTest1%unique(by=(“level1”,“Hey Andrew,你能解释一下你的代码和我的代码之间的区别吗:abcTest1%unique(by=c(“level1”,“patientId”,“value”))abcTest1%group_by(level1,patientId,value)%>%slice(1)我检查了我的代码得到的输出与你的相同,我没有