查看原文
其他

凡是重复的,全部删掉,一个都不留!

果子 果子学生信 2023-06-15

今天值得纪念。

R语言里面的去重,有两种
一种是重复项里面我们保留一个,典型的应用是探针去重
GEO芯片中多个探针对应一个基因,是求平均值还是保留最大值?

另外一种是假如重复了,全部删掉,一个不留,典型的应用是
如果GEO中一个探针对应多个基因,如何把这个探针全部删掉?

最近我们碰到了解决第二个问题的好方法,现在来重新讲一下,正好介绍几个小函数。
创建一个数据框,第一列是字母,第二列是数字,字母明显有重复,重复项是A和C

a <- c(rep("A"3), rep("B"1), rep("C",2),LETTERS[4:7])
b <- c(1,1,2,4,1,2,2,5,6,5)
df <-data.frame(a,b,stringsAsFactors = F)
df
   a b
1  A 1
2  A 1
3  A 2
4  B 4
5  C 1
6  C 2
7  D 2
8  E 5
9  F 6
10 G 5

table函数可以展示重复项的频数

table(df$a)
A B C D E F G 
3 1 2 1 1 1 1 

这个函数我特别喜欢,还自己写过函数来实现同样的功能,可以看一下这个良心帖子
R语言中性价比最高的函数以及最贵的函数

除此之外,还有一个操作可以实现同样的功能,比如group_by联合summarise函数,可以实现分组内批量操作

library(dplyr)
df %>% 
  group_by(a) %>% 
  summarise(n=n())
# A tibble: 7 x 2
  a         n
  <chr> <int>
1 A         3
2 B         1
3 C         2
4 D         1
5 E         1
6 F         1
7 G         1

其中n()表示分组内的数据计算次数

如果想看分组批量操作,这边有一个超有诚意的帖子,介绍了13中方法
R语言学习路上的忆苦思甜

还有一个简便的方法也可以实现table的操作,就是dplyr中的count函数

df %>% 
  count(a)
# A tibble: 7 x 2
  a         n
  <chr> <int>
1 A         3
2 B         1
3 C         2
4 D         1
5 E         1
6 F         1
7 G         1

如果整的复杂一点,还可以清楚能做任何事情的do,这个在分组计算里面据说很重要,可以上天入地,但是我现在还没有这个需求,目前就把它放在地里,没拔出来。

df %>% 
  group_by(a) %>% 
  do(data.frame(nrow=nrow(.)))
# A tibble: 7 x 2
# Groups:   a [7]
  a      nrow
  <chr> <int>
1 A         3
2 B         1
3 C         2
4 D         1
5 E         1
6 F         1
7 G         1

以上是闲话,都是为了展现重复项的频次,现在要开始去掉所有重复项了。
如果有基础函数,可以这样,先把重复项找出来

unique(df$a[duplicated(df$a)])
[1"A" "C"

然后再看这些重复项在原来数据集中的位置,最终去掉他们

df[!(df$a %in% unique(df$a[duplicated(df$a)])),]
   a b
4  B 4
7  D 2
8  E 5
9  F 6
10 G 5

这个可以的,但是你要上课这么讲,估计大家都会死在这里,听不下去了。
我们换个方法,我们只要先计算频次,然后选择频次等于1的,就是非重复项了,最终跟原数据交叉合并一下,就可以了

df %>% 
  count(a) %>% 
  filter(n==1) %>% 
  inner_join(df,by="a") %>% 
  select(-n)
# A tibble: 5 x 2
  a         b
  <chr> <dbl>
1 B         4
2 D         2
3 E         5
4 F         6
5 G         5

这是我以前的极限,我大概都会这么做,但是我们上海班的同学学习比较积极,天天群里几百条信息,我看到有个同学介绍了新的方法,很巧妙,原理就是用n()分组计算次数,添加新的列,然后选出频次为1的行就可以

df %>% 
  group_by(a) %>% 
  mutate(n=n()) %>% 
  filter(n==1) %>% 
  select(-n)
# A tibble: 5 x 2
# Groups:   a [5]
  a         b
  <chr> <dbl>
1 B         4
2 D         2
3 E         5
4 F         6
5 G         5

巧就巧妙在,我一直以为,n()只能出现在summarise函数中,没想到mutate增加列的函数中也可以直接调用
既然这样,我就施展了问号大法

?n()

帮助文档里面直接说,这个函数n()只能用于三个函数内部,分别是summarise,mutate,filter。前两个我们都碰到了,第三个是筛选行的函数,那岂不是刚好满足要求,所以我实现了一个删除所有重复项的极简操作

df %>% 
  group_by(a) %>% 
  filter(n()==1)
# A tibble: 5 x 2
# Groups:   a [5]
  a         b
  <chr> <dbl>
1 B         4
2 D         2
3 E         5
4 F         6
5 G         5

如果我想把第一列抽离出来,我还可以用pull函数出来

df %>% 
  group_by(a) %>% 
  filter(n()==1) %>% 
  pull(a)
[1"B" "D" "E" "F" "G"

好了,今天就到这里。

这周会成为科研生活中最重要的一周,昨天我完成了5人组成的专家团的进度考核,在那之前三天没怎么睡觉。
今天完成了重要样本的收集,以此留念。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存