刘小泽写于19.9.13
从一个小问题也能学到很多
原本是一件很简单的事情
用R读取一个数据,本来是一件很简单的事情,但用两种方法探索时发现了一些端倪
例如:
我们可以清楚看到原来的列名中是有-
的
接下来,用R读入试试。我之所以发现这个问题,是因为教程中使用了read.delim
,它的代码如下:
# 第一种read.delim
plate1 <- read.delim(file.path(tempdir(), "counts_Calero_20160113.tsv"),
header=TRUE, row.names=1, check.names=FALSE)
> dim(plate1)
[1] 46703 97
> head(names(plate1))
[1] "Length"
[2] "SLX-9555.N701_S502.C89V9ANXX.s_1.r_1"
[3] "SLX-9555.N701_S503.C89V9ANXX.s_1.r_1"
[4] "SLX-9555.N701_S504.C89V9ANXX.s_1.r_1"
[5] "SLX-9555.N701_S505.C89V9ANXX.s_1.r_1"
[6] "SLX-9555.N701_S506.C89V9ANXX.s_1.r_1"
可以看到它复现了原来数据的-
但问题来了
我在使用read.csv
的时候,出现了一点问题,本来想的是就是简单验证一下,结果报了一个FALSE
# 第二种read.csv
tmp1 <- read.csv(file.path(tempdir(), "counts_Calero_20160113.tsv"),
row.names = 1, sep = '\t',header = T )
> dim(tmp1)
[1] 46703 97
# 它们竟然不一样!
> identical(plate1,tmp1)
[1] FALSE
到底是哪里不一样?我也不清楚,于是使用了另外一个函数来获得更多的信息:
# 这个函数除了判断二者是否一样,还能给出一点提示信息
> all.equal(tmp1,plate1)
[1] "Names: 96 string mismatches"
根据结果提示:应该是有96个列名不一样,因为names()
是取列名的意思
所以我又检查了一下列名:
> head(names(tmp1))
[1] "Length"
[2] "SLX.9555.N701_S502.C89V9ANXX.s_1.r_1"
[3] "SLX.9555.N701_S503.C89V9ANXX.s_1.r_1"
[4] "SLX.9555.N701_S504.C89V9ANXX.s_1.r_1"
[5] "SLX.9555.N701_S505.C89V9ANXX.s_1.r_1"
[6] "SLX.9555.N701_S506.C89V9ANXX.s_1.r_1"
结果和read.delim()
结果确实差在了-
变成.
重新检查
我又怀疑是不是这两个函数得到不一样,但是使用help()
查看的时候,发现它们又都是属于read.table {utils}
,按说得到的东西应该是一样的。那么 是不是参数的设置?
于是发现我使用的read.csv
相比于read.delim
缺少了一个参数:check.names
,而这个参数我平常是忽视的,那么在read.csv()
中添加上check.names
参数会怎样呢?
tmp2 <- read.csv(file.path(tempdir(), "counts_Calero_20160113.tsv"),
row.names = 1, sep = '\t',header = T ,check.names = F)
> head(names(tmp2))
[1] "Length"
[2] "SLX-9555.N701_S502.C89V9ANXX.s_1.r_1"
[3] "SLX-9555.N701_S503.C89V9ANXX.s_1.r_1"
[4] "SLX-9555.N701_S504.C89V9ANXX.s_1.r_1"
[5] "SLX-9555.N701_S505.C89V9ANXX.s_1.r_1"
[6] "SLX-9555.N701_S506.C89V9ANXX.s_1.r_1"
发现确实保持了和原来的一致性!
探索
那么,问题来了,这个参数
check.names
做了什么?它为什么会私自改变列名?
再次搜索帮助文档:
发现这个函数确实是说,如果有必要,它会进行make.names()
处理,而这个函数所做的的事情,也就是把不识别的字符变成.
怎么体现不识别呢?简单用$
取一下列名就能看到:
# 如果是用原来数据的列名
> head(plate1$`SLX-9555.N701_S502.C89V9ANXX.s_1.r_1`)
[1] 0 0 0 0 0 0
# 而如果用R私自修改过的
> head(tmp$SLX.9555.N701_S502.C89V9ANXX.s_1.r_1)
[1] 0 0 0 0 0 0
很明显可以看到,R对第一个列名加上了反引号,再次验证了R不识别列名中包含的-
因此,这次得到的结论就是
R认为列名中的短横线
-
是无效的(当然还会有其他字符),所以如果读入的列名中包含了-
,它会默认将其替换为.
,目的是确保能及时检验是否出现重复的列名如果原本数据中的列名包括
-
或者其他R不识别的字符,自己还想让读到R的数据与原数据保持一致,就需要使用check.names = FALSE
不让read.csv
或者read.delim
读入的数据框中列名的-
变成.
欢迎关注我们的公众号~_~
我们是两个农转生信的小硕,打造生信星球,想让它成为一个不拽术语、通俗易懂的生信知识平台。需要帮助或提出意见请后台留言或发送邮件到[email protected]