R|ggplot2(三)|coord 系列函數坐標軸轉換

coord_ 系列函數可以改變xy軸的位置,默認使用 coord_cartesian(),我們可以改變成如下幾種

coord_cartesian 默認情況,指定參數則控制圖形特定區域放大顯示ncoord_fixed 圖形伸縮變換ncoord_flip 橫縱坐標位置轉換ncoord_polar 彎曲橫縱坐標(畫餅圖可以用)ncoord_map 將地圖變成球狀展示(這個我們以後講到地圖再專門說)ncoord_trans 轉化數據n

coord系列函數隻影響圖形展示,不影響內部數據的值。即使用原數據作圖,再對圖形進行變動

coord_cartesian(xlim = NULL, ylim = NULL, expand = TRUE)

如果不加參數,就是默認的圖形,和不加這個函數一樣

  • xlim 和 ylim 各接一個二元數值向量,控制顯示的區域範圍,原理不是截取,而是放大該區域,原有圖形不變,超出此範圍的點也可以照常顯示
  • expand 為T則默認指定xlim軸兩端還留一些空隙,F則控制範圍即為圖形的邊緣

library(ggplot2)np0 <- ggplot(mtcars, aes(wt, drat)) + geom_point()np0np0 + coord_cartesian() # 沒有變化np0 + coord_cartesian(xlim = c(2, 4))np0 + coord_cartesian(xlim = c(2, 4), expand = F)n

coord_fixed(ratio = 1, xlim = NULL, ylim = NULL, expand = TRUE)

其他參數和上面相同,ratio表示縱軸1單位顯示的長度,是橫軸1單位顯示的長度的幾倍。比如xy軸都是0-5cm的數據,ratio=2則圖形高和寬的比是2:1,即縱軸的1cm顯示出來的長度是橫軸的兩倍。所以ratio越小,圖形越扁

p0np0 + coord_fixed(ratio = 1)np0 + coord_fixed(ratio = 1/2)np0 + coord_fixed(ratio = 2)n

coord_flip(xlim = NULL, ylim = NULL, expand = TRUE)

橫縱軸位置互換,沒有特殊參數

p0np0 + coord_flip()n

coord_polar(theta = "x", start = 0, direction = 1)

上面我們提到過如何使用這個函數將柱狀圖轉化為餅圖,現在我們對這個圖形的參數進行簡單調整

  • start 接一個弧度制角度,看餅圖起始點放在哪個角度上
  • direction默認為1,各個元素順時針排列下去,如果是-1則逆時針

pp <- ggplot(mpg, aes(1, fill=class))+geom_bar()nppnpp + coord_polar(theta = "y")npp + coord_polar(theta = "y", start = pi/3)npp + coord_polar(theta = "y", direction = -1)n

其實我們會發現,做出來的圖形雖然樣子像餅圖,但是標度什麼的都不盡如人意,都需要後期使用其他方法調整,可以看出ggplot2包對餅圖的支持是不強的,這個Hadley本人對餅圖的排斥也有關係,餅圖絕大多數都可以使用柱狀圖代替。

coord_trans(x = "identity", y = "identity", limx = NULL, limy = NULL, xtrans, ytrans)

將數據轉換為想要的形式,再進行作圖,最常見的是取對數。它跟scale_x_log10()函數還是有區別的。

  • 後者等價於先將數據取對數,再拿進來處理
  • 前者則是其他處理優先,最後作圖時再取對數。

    我們拿擬合曲線舉例子
  • 我們如果用scale_x_log10就相當於把x的數據取了對數放進來做回歸,擬合出一條直線。
  • 如果使用coord_trans則是先用原有數據進行回歸,得到一條擬合直線之後再變換坐標軸

a <- seq(-5,2,len=30) + abs(rnorm(30,0,0.1))nb <- exp(seq(-5,2,len=30)) + abs(rnorm(30,0,0.1)) + 10ndf <- data.frame(a,b)nps <- ggplot(df, aes(a,b)) + geom_point() +n coord_fixed(ratio=1)+n geom_smooth(method="lm")npsnn# 使用log之後的y來做nggplot(df, aes(a,log10(b))) + geom_point() +n coord_fixed(ratio=1)+n geom_smooth(method="lm")nn# 同上nps + scale_y_log10()nn# 使用coord_transn# ps + coord_trans(y = "log10") # 因為擬合出的曲線y出現負值,所以無法對y取對數,此處報錯n# 我們可以取其中一部分來做ndf1 <- df[df$a>0,]nggplot(df1, aes(a,b)) + geom_point() +n coord_fixed(ratio=1)+n geom_smooth(method="lm") +n coord_trans(y="log10")n

我們發現使用coord_trans時,擬合出來的曲線發生了彎曲。那是因為是先使用原有數據擬合出了一條直線,之後再改變坐標軸作圖,所以曲線也被彎曲了。這不同於直接對數據進行變換的情況。

下面我們討論當我們需要進行其他變換時應該怎麼做。

我們需要使用scales包

library(scales)npt <- ggplot(df, aes(a,b)) + geom_point() +n coord_fixed(ratio=1)nptnpt + coord_trans(y="log10")nnggplot(df, aes(a,b)) + geom_point() +n coord_fixed(ratio=1)+n coord_trans(x=exp_trans(exp(1)))n

下面使用的exp_trans函數相當於把x軸取了e的指數,這是scales包中的函數,查看exp_trans函數源碼

function (base = exp(1)) n{n trans_new(paste0("power-", format(base)), n function(x) base^x, n function(x) log(x, base = base))n}n<environment: namespace:scales>n

我們可以看到,這是由此包中的trans_new函數創建出來的,所以為了更靈活地使用這種變換,我們需要學習trans_new函數。

我們需要看trans_new函數的參數,而為了了解它參數的含義,我們可以去查看它的源碼。我們發現這個函數作用後返回一個list,結合ggplot2的使用,則相當於ggplot2在調用list中的一些元素,我們可以知道調用時哪些參數才是真正重要的。我們主要使用transform/inverse/domain三個參數

  • transform 接一個函數,數據要作為參數輸入,表用怎麼使用數據x
  • inverse 輸入transform 的反作用函數
  • domain 接一個二元數值向量,表明只對這個範圍之內的數據實行這種變換
  • name參數是什麼都無所謂(但是必須要有),其實在這裡inverse參數是什麼也無所謂

接下來,我們再注意一個細節

ggplot(df, aes(exp(a),b)) + geom_point()nggplot(df, aes(a,b)) + geom_point() +n coord_trans(x=exp_trans(exp(1)))n

這兩個圖形狀相同,但是要注意x軸標度不同,前者就是使用轉化之後數值作為標度,而後者則是使用原來數值作為標度,而標度之間的距離卻被扭曲了,這正是coord類函數所做的事情,只是對軸進行更改,數據都是原來的沒有變化。

正因為此,所以當我們自己用 trans_new 函數創建變化時,像加減乘除這樣的運算,就不會對圖形有任何更改。因為這樣沒有改變點之間的密集分布情況,壓縮下來還是一樣。

專欄信息

專欄主頁:Data Analysis

專欄目錄:目錄


推薦閱讀:

《R語言實戰》第一、二章實戰練習
七周成為數據分析師:快速掌握麥肯錫的分析思維
我們做了一款詞雲小工具
《R語言實戰》第六章學習筆記

TAG:R编程语言 | ggplot2 | 数据分析 |