問題背景
https://mp.weixin.qq.com/s/DFIwVwrgN4s-FK4WjWuO3Q
在這一篇推文里,我寫了怎么正確顯示坐標軸順序。
不調(diào)整的話橫坐標默認是這樣:

調(diào)整正確的是這樣:

然而有位學(xué)員搬磚的時候報了錯。
示例流程
1.生成示例數(shù)據(jù)
if(!require(tidyr)) install.packages("tidyr")
#> Loading required package: tidyr
library(tidyr)
x=matrix(rnorm(2200,mean=1.5,sd = 0.2),ncol = 22)
test=as.data.frame(x)
colnames(test)=paste0("chr",1:22)
test2 <- gather(test,key = "chr",value = "values")
head(test2,3)
#> chr values
#> 1 chr1 1.173558
#> 2 chr1 1.749868
#> 3 chr1 1.374387
table(test2$chr)
#>
#> chr1 chr10 chr11 chr12 chr13 chr14 chr15 chr16 chr17 chr18 chr19 chr2
#> 100 100 100 100 100 100 100 100 100 100 100 100
#> chr20 chr21 chr22 chr3 chr4 chr5 chr6 chr7 chr8 chr9
#> 100 100 100 100 100 100 100 100 100 100
2.調(diào)整橫軸對應(yīng)列的順序
關(guān)鍵代碼是:
test2$chr <- factor(test2$chr,levels=paste0("chr",1:22),ordered = TRUE)
3.出圖
順利做出了正確的圖
if(!require(ggplot2))install.packages("ggplot2")
#> Loading required package: ggplot2
library(ggplot2)
p1 <- ggplot(test2,aes(x = chr, y = values)) +
geom_boxplot()+
theme_bw()+
theme(axis.text.x = element_text(angle=50,vjust = 0.5))
p1

翻車現(xiàn)場
這么簡單的代碼,發(fā)生了報錯。
錯誤代碼
options(stringsAsFactors = F)
a <-data.frame(case=paste("S",c(1:50)),values=runif(50))
a$case <- factor(a$case,levels=paste0("S",1:50),ordered = TRUE)
plot(a$case,a$values)
warning和報錯信息
#> Warning in min(x): no non-missing arguments to min; returning Inf
#> Warning in max(x): no non-missing arguments to max; returning -Inf
#> Error in plot.window(xlim = xlim, ylim = ylim, log = log, yaxs = pars$yaxs): need finite 'ylim' values
有報錯,請搜索
直接復(fù)制到必應(yīng)搜索,可以看到這個鏈接:
https://stackoverflow.com/questions/21349368/error-in-plot-window-need-finite-xlim-values
總結(jié)一下答案的意思,其實就是數(shù)據(jù)全是NA。一檢查,果不其然,全是NA。
a$case
#> [1] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
#> [15] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
#> [29] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
#> [43] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
#> 50 Levels: S1 < S2 < S3 < S4 < S5 < S6 < S7 < S8 < S9 < S10 < ... < S50
為何都是NA
這樣一個簡單的報錯竟然花了我十幾分鐘時間去解決,我先后測試了這個數(shù)據(jù)有沒有問題,分別用ggplot2和plot作圖,plot支不支持因子型數(shù)據(jù),然后又看了因子水平是不是不能有空格。
(叫苦不迭,我根本沒有學(xué)過基礎(chǔ)包作圖,我是直接學(xué)的ggplot2啊啊啊啊,而且因子挖的坑,早就被哈德雷叔叔填平了,如果不是在后面的教學(xué)中必須要講基礎(chǔ)包,我可能碰都不碰它。)
火眼金睛
全是NA的原因非常簡單,因子水平和內(nèi)容完全不對應(yīng),內(nèi)容用的函數(shù)是paste,水平用的函數(shù)卻成了paste0。
paste0("S",1:50)
#> [1] "S1" "S2" "S3" "S4" "S5" "S6" "S7" "S8" "S9" "S10" "S11"
#> [12] "S12" "S13" "S14" "S15" "S16" "S17" "S18" "S19" "S20" "S21" "S22"
#> [23] "S23" "S24" "S25" "S26" "S27" "S28" "S29" "S30" "S31" "S32" "S33"
#> [34] "S34" "S35" "S36" "S37" "S38" "S39" "S40" "S41" "S42" "S43" "S44"
#> [45] "S45" "S46" "S47" "S48" "S49" "S50"
paste("S",1:50)
#> [1] "S 1" "S 2" "S 3" "S 4" "S 5" "S 6" "S 7" "S 8" "S 9" "S 10"
#> [11] "S 11" "S 12" "S 13" "S 14" "S 15" "S 16" "S 17" "S 18" "S 19" "S 20"
#> [21] "S 21" "S 22" "S 23" "S 24" "S 25" "S 26" "S 27" "S 28" "S 29" "S 30"
#> [31] "S 31" "S 32" "S 33" "S 34" "S 35" "S 36" "S 37" "S 38" "S 39" "S 40"
#> [41] "S 41" "S 42" "S 43" "S 44" "S 45" "S 46" "S 47" "S 48" "S 49" "S 50"
改正
其實想讓這個代碼正確運行異常簡單,就加一個零而已。
a<-data.frame(case=paste0("S",c(1:50)),values=runif(50))
a$case <- factor(a$case,levels=paste0("S",1:50),ordered = TRUE)
plot(a$case,a$values)

后記
對于新手來說很多細微的小錯誤,卻是越不過去的大坎。當你回過頭去看看,會發(fā)現(xiàn)曾經(jīng)的錯誤其實特別簡單。
看別人的錯誤代碼真要命啊。前面寫paste,后面寫paste0。雖然單獨拿出來都沒錯,但是湊在一起就不對了。
/(ㄒoㄒ)/~~
如果一個人愿意花時間幫你找你寫的代碼報錯原因,那。。。她心情一定很好。
看完這代碼,心情怎么樣就不一定了。比如我現(xiàn)在就想暴走。