手把手教你使用ggplot2繪製散點圖

作者:劉順祥 公眾號:數據分析1480 (微信ID:lsxxx2011)

配套教程:手把手教你做文本挖掘 edu.hellobi.com/course/

散點圖可以用來描述兩個連續變數之間的關係,一般在做數據探索分析時會使用到,通過散點圖發現變數之間的相關性強度、是否線性關係等。

繪製簡單的散點圖

ggplot包中的geom_point()函數可以非常方便繪製出所需的散點圖。

library(ggplot2)set.seed(1234)x <- rnorm(100,mean = 2, sd = 3)y <- -1.5 + 2*x + rnorm(100)df <- data.frame(x = x, y = y)ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point()

繪製分組的散點圖

可將分組變數(因子或字元變數)賦值給顏色或形狀屬性,實現分組散點圖的繪製

set.seed(1234)x <- rnorm(100,mean = 2, sd = 3)y <- -1.5 + 2*x + rnorm(100)z <- sample(c(0,1), size = 100, replace = TRUE)df <- data.frame(x = x, y = y, z = z)#將數值型變數轉換為因子型變數df$z <- factor(df$z)#分組變數賦值給顏色屬性ggplot(data = df, mapping = aes(x = x, y = y, colour = z)) + geom_point(size = 3)

#分組變數賦值給形狀屬性ggplot(data = df, mapping = aes(x = x, y = y, shape = z)) + geom_point(size = 3)

用戶可能對默認的顏色或形狀不滿意,可以通過scale_colour_brewer()或scale_colour_manual()函數自定義點的顏色;通過scale_shape_manual()函數實現自定義點的形狀。為了說明問題,這裡將分組變數同時賦值給顏色屬性和形狀屬性。

ggplot(data = df, mapping = aes(x = x, y = y, colour = z, shape = z)) + geom_point(size = 3) + scale_color_brewer(palette = Accent) + scale_shape_manual(values = c(2,16))

有關可選的點的形狀可參考下圖:

這裡需要提醒的是,21-25之間的點形狀,既可以賦值邊框顏色,又可以賦值填充色,當數據點顏色較淺時,帶邊框線的點就顯得尤為重要,這樣可以將數據點與背景色區分開來,而0-20之間的點形狀,只能賦值邊框顏色。

以上幾種圖形是將離散變數或因子映射給顏色屬性或形狀屬性,下面介紹如何將連續變數映射給顏色屬性或大小屬性。

x <- c(10,13,11,15,18,20,21,22,24,26)y <- c(76,60,70,58,55,48,44,40,26,18)z <- c(100,120,300,180,80,210,30,95,145,420)df <- data.frame(x = x, y = y, z = z)#將連續變數映射給顏色屬性ggplot(data = df, mapping = aes(x = x, y = y, colour = z)) + geom_point(size = 3)

但這裡發現一個問題,顏色越深而對應的值越小,如何將值的大小與顏色的深淺保持一致呢?很簡單,只需人為的設置色階,從低到高設置不同的顏色即可。

ggplot(data = df, mapping = aes(x = x, y = y, colour = z)) + geom_point(size = 3) + scale_colour_gradient(low = lightblue, high = darkblue)

#將連續變數映射給大小屬性

ggplot(data = df, mapping = aes(x = x, y = y, size = z)) + geom_point()

上面將連續變數賦值給顏色屬性或大小屬性,我們還可以人為的設置色階間隔或大小間隔。

#自定義色階間隔ggplot(data = df, mapping = aes(x = x, y = y, fill = z)) + geom_point(shape = 21, size = 3) + scale_fill_continuous(low = lightblue, high = darkblue, breaks = c(100,150,200,300,350,400))

#自定義球大小的間隔ggplot(data = df, mapping = aes(x = x, y = y, size = z)) + geom_point() + scale_size_continuous(breaks = c(100,150,200,300,350,400), guide = guide_legend())

#將連續變數值的大小與球的大小成比例ggplot(data = df, mapping = aes(x = x, y = y, size = z)) + geom_point() + scale_size_area(max_size = 10)

很明顯,使用第二種球大小的圖看起來更舒服,也更明顯。

重疊點的處理

當數據點非常多時,可能會導致數據點重疊非常嚴重,該如何處理這樣的問題呢?一般有以下幾種方法:

1)使用半透明的點

2)數據分箱,並用矩形表示

3)數據分箱,並用六邊形表示

4)使用二維密度估計,並將等高線添加到散點圖中

5)向散點圖中添加邊際地毯

set.seed(1234)x <- rnorm(10000)y <- rnorm(10000,0,2)df <- data.frame(x = x, y = y)#不作任何處理ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point()

#使用透明度處理點的重疊問題ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point(alpha = 0.1)#分箱,並用矩陣表示ggplot(data = df, mapping = aes(x = x, y = y)) + stat_bin2d()

默認情況下,stat_bin_2d()函數將x軸和y軸的數據點各分為30個段,即參數900個箱子,用戶還可以自定義分段個數,以及箱子在垂直和水平方向上的寬度。

#設置bins為50ggplot(data = df, mapping = aes(x = x, y = y)) + stat_bin2d(bins = 50) + scale_fill_gradient(low = steelblue, high = darkred, limits = c(0,100), breaks = c(0,25,50,100))

將圖形劃分為小的正方形箱可能會產生分散注意力的視覺假象,一般建議使用六邊形代之。

#分箱,並用六邊形表示ggplot(data = df, mapping = aes(x = x, y = y)) + stat_binhex(binwidth = c(0.2,0.3)) + scale_fill_gradient(low = lightgreen, high = darkred, limits = c(0,100), breaks = c(0,25,50,100))

#使用stat_density2d作二維密度估計,並將等高線添加到散點圖中ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point() + stat_density2d()

#使用大小與分布密度成正比例的點ggplot(data = df, mapping = aes(x = x, y = y)) + stat_density2d(geom = point, aes(size = ..density..), contour = FALSE) + scale_size_area()

#使用熱圖展示數據分布密度情況ggplot(data = df, mapping = aes(x = x, y = y)) + stat_density2d(geom = tile, aes(fill = ..density..), contour = FALSE)

#向散點圖中添加邊際地毯ggplot(data = faithful, mapping = aes(x = eruptions, y = waiting)) + geom_point() + geom_rug()

通過邊際地毯,可以快速查看每個坐標軸上數據的分布密疏情況。還可以通過向邊際地毯線的位置坐標添加擾動並設定size減少線寬,從而減輕邊際地毯線的重疊程度。

ggplot(data = faithful, mapping = aes(x = eruptions, y = waiting)) + geom_point() + geom_rug(position = jitter, size = 0.1)

如果一個變數為離散變數,另一個變數為連續變數時,如何繪製散點圖?

set.seed(1234)x <- rep(1:5, each = 1000)y <- c(rnorm(1000),rnorm(1000,1,2),rnorm(1000,3,4),rt(1000,2),rt(1000,4))df <- data.frame(x = x, y = y)df$x <- factor(df$x)#不作任何處理的散點圖ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point()

對於這樣的圖,似乎沒有什麼意義,為了避免過度重疊,有以下兩種處理方法:

1)使用擾動圖

2)使用箱線圖(適用於一個或兩個變數為離散變數)

#給數據點添加隨機擾動ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point(position = jitter)

默認情況下,擾動函數在每個方向(水平和垂直)上添加的擾動值為數據點最小精度的40%,當然也可以通過width和height參數自定義擾動量。

ggplot(data = df, mapping = aes(x = x, y = y)) + geom_point(position = position_jitter(width = 0.5, height = 0))

上圖只在水平方向上添加50%的擾動量。

#繪製箱線圖ggplot(data = df, mapping = aes(x = x, y = y)) + geom_boxplot(mapping = aes(group = x), fill = steelblue)

這裡需要提醒的是,橫坐標為數值型變數時,必須要將其轉換為因子,並在geom_boxplot()函數的屬性中將因子映射給group,否則產生的效果圖將是錯誤的。

上文中提到,通過繪製兩個變數的散點圖可以查看變數將的關係,可以是線性的也可以是非線性的,如何在散點圖的基礎上再添加擬合曲線呢?下文將逐一介紹幾種擬合線。

#不添加任何擬合線ggplot(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width, colour = Species)) + geom_point()

#添加線性擬合線ggplot(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width, colour = Species)) + geom_point() + stat_smooth(method = lm)

#添加局部加權多項式曲線ggplot(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width, colour = Species)) + geom_point() + stat_smooth(method = loess)

#添加Logistic曲線library(MASS)b <- biopsy#繪製Logistic曲線必須將因變數強制轉換為0-1b <- transform(b, class_trans = ifelse(class == benign, 0, 1))ggplot(data = b, mapping = aes(x = V1, y = class_trans)) + geom_point(position = position_jitter(width = 0.3, height = 0.06), alpha = 0.4, shape = 21, size = 2) + stat_smooth(method = glm, method.args = list(family = "binomial"))

如果不需要為擬合線繪製置信區間的話,置信將stat_smooth()函數中的參數se設為FALSE即可。

如果兩個變數均是離散變數,該如何繪製散點圖?實質上,這樣的散點圖我們稱作氣泡圖。一般可以將這種圖應用到價值轉移中。

value1 <- rep(c(高價值,中價值,低價值), each = 3)value2 <- rep(c(高價值,中價值,低價值), times = 3)nums <- c(500,287,123,156,720,390,80,468,1200)df <- data.frame(value1 = value1, value2 = value2, nums = nums)df$value1 <- factor(df$value1, levels = c(高價值,中價值,低價值), order = TRUE)df$value2 <- factor(df$value2, levels = c(低價值,中價值,高價值), order = TRUE)ggplot(data = df, mapping = aes(x = value1, y = value2, size = nums)) + geom_point(colour = steelblue) + scale_size_area(max_size = 30, guide = FALSE) + geom_text(aes(label = nums), vjust = 0, colour = black, size = 5)

從圖中可知,高價值用戶中有80個流向了低價值,而低價值用戶中又有128個流向高價值。

最後再介紹兩種比較常用的種散點圖,即Cleveland點圖和散點圖矩陣

在《手把手教你使用ggplot2繪製條形圖》我們向大家介紹了然後繪製各種各樣的條形圖,這裡介紹另一種替代條形圖的Cleveland點圖。通過Cleveland點圖可以減少圖形造成的視覺混亂,同時圖形更具可讀性。

set.seed(1234)names <- lettersScore <- runif(26, min = 55, max = 90)df <- data.frame(names = names, Score = Score)#條形圖ggplot(data = df, mapping = aes(x = reorder(names,Score), y = Score)) + geom_bar(stat = identity, fill = steelblue, colour = black) + xlab(Name) + geom_text(aes(label = round(Score)), vjust = 1)

#Cleveland點圖ggplot(data = df, mapping = aes(x = reorder(names,Score), y = Score)) + geom_point(size = 5, shape = 21, fill = steelblue, colour = black) + xlab(Name)

散點圖矩陣是一種對多個變數兩兩之間關係進行可視化的有效方法,R中pairs()函數可以實現這樣的需求。

#使用pairs()函數繪製散點圖矩陣data(tips, package = "reshape")pairs(tips[,1:3])#使用car包中的scatterplot.matrix()函數library(car)scatterplot.matrix(tips[,1:3])

#使用GGally包中的ggpairs()函數繪製散點圖矩陣library(GGally)ggpairs(tips[, 1:3])

通過GGally包中的ggpairs()函數繪製散點圖矩陣還是非常引入入目的,將連續變數和離散變數非常完美的結合在一起。

參考資料:

R語言_ggplot2:數據分析與圖形藝術

R數據可視化手冊

推薦閱讀:

3. 如何設定分析目標
「異類」年度大數據引領消費生態大進化
大數據分析第四關學習筆記
大數據發展的三重門

TAG:R編程語言 | 數據分析 | 大數據分析 |