凡是重复的,全部删掉,一个都不留!
今天值得纪念。
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人组成的专家团的进度考核,在那之前三天没怎么睡觉。
今天完成了重要样本的收集,以此留念。