R给你的数据化了妆?
小伙伴说他写个CSV文件,名字就变了,无缘无故|
就被改了,还有些名字被强加了X
。我注意到了他写的对象是data.frame(d)
,这锅绝对是data.frame
的。
我们可以试一下:
> d = matrix(rnorm(4), ncol=2)
> colnames(d) = c("A|B", "123")
> write.csv(data.frame(d))
"","A.B","X123"
"1",-0.601247669017546,0.802654193340092
"2",-0.128752028398414,0.430829592244036
没错,自己给变了。
其实如果我们不data.frame
强转的话,一切都是OK的。
> write.csv(d)
"","A|B","123"
"1",-0.601247669017546,0.802654193340092
"2",-0.128752028398414,0.430829592244036
我们不防再试一下,自己转为data.frame
,看看是不是这样,结果必须也是,所以这锅就是data.frame
的。
> d = data.frame(d)
> colnames(d)
[1] "A.B" "X123"
解决方案
既然转成data.frame
之后,它变了,那我们就再变回去呗。
> colnames(d) = c("A|B", "123")
> colnames(d)
[1] "A|B" "123"
> write.csv(d)
"","A|B","123"
"1",-0.601247669017546,0.802654193340092
"2",-0.128752028398414,0.430829592244036
问题到底出在那里?
因为|
是保留字符,还有数字不能当变量名这些,几乎是共识,所以data.frame()
这个函数就不允许它们当名字。但是我们想一想,保留字符出现在字符串中是OK的吧?数字开头的字符串是OK的吧?必须是,而名字必须就只是单纯的字符串吧?必须也是,所以这是两码事,你看我们可以给d
的colnames设置回去就知道了,这些都是合法的!到了这里,我们只能说data.frame()
这个函数死蠢!
第二点,你可能以为是matrix转data.frame才会有这问题, 那我们可以再试一下,data.frame转data.frame,你以为它啥都不干吧,不是的,data.frame()
这个函数,就是会给你改名字,给你惊喜。
> write.csv(data.frame(d))
"","A.B","X123"
"1",-0.601247669017546,0.802654193340092
"2",-0.128752028398414,0.430829592244036
> class(d)
[1] "data.frame"
如何能够避免这个坑
使用data.frame(d, check.names=FALSE)
或者使用tibble
:
> tibble::as_data_frame(d) %>% write.csv
"","A|B","123"
"1",-0.601247669017546,0.802654193340092
"2",-0.128752028398414,0.430829592244036