专栏名称: EasyCharts
EasyCharts,易图表,我们将定期推送各种数据可视化与分析教程,包括Excel(Power BI)、Origin、Sigmaplot、GraphPad、R、Python、Matlab、Tableau、D3.js等。
目录
相关文章推荐
前端早读课  ·  【第3436期】再见Postman,你好In ... ·  昨天  
前端大全  ·  图解Nestjs - 适合中国宝宝的入门指导 ·  2 天前  
前端早读课  ·  【早阅】Cursor ... ·  2 天前  
前端早读课  ·  【早阅】适配器和组合设计模式 ·  3 天前  
前端早读课  ·  【第3435期】构建更高效的 React ... ·  4 天前  
51好读  ›  专栏  ›  EasyCharts

如何用kandinsky抽象画呈现数据集

EasyCharts  · 公众号  · 前端  · 2017-08-07 08:00

正文

声明:本文最早由Giora Simchoni发表在自己的博客由周世荣翻译.

kandinsky 是一个著名的俄罗斯抽象派艺术家,以大胆使用多彩的几何形状而出名. 他的作品中常用的几何形状有矩形、圆、三角形、弧、波浪线和十字图案. 这些几何图案除后两个外,R中的grid包都提供了相应的函数。下面我们一一介绍如何绘制这些几何图案。

矩形

首先使用grd.new()函数绘制一张空白画板,这张画板的XY轴的范围0-1,从左下角(x=0,y=0)到右上角(x=1,y=1). 然后使用grid.rect函数绘制矩形, 其中x=0.4,y=0.6表示矩形中心在画板上的坐标,width 和 height 表示矩形的宽和高, gp参数通过gpar函数来自定义矩形属性, 例如本例中定制了一个红边宽度为2的矩形

#加载grid包
library(grid)
#绘制新的画板
grid.newpage()
#绘制矩形
grid.rect(x = 0.4, y = 0.6, width = 0.5, height = 0.4,   gp = gpar(col = "red", lwd = 2))

那么,如何定制一个有倾斜的矩形呢?遗憾的是grid.rect中并没有相应的angle参数. 此时我们可以换一种思路,既然矩形不能倾斜,那么我们就让画板倾斜,使用viewport在空白画板上创建一个倾斜45度子画板,然后再子画板上作图.

vp1 0.5, y = 0.6, width = 0.8, height = 0.7, angle = 45)
grid.rect(x = 0.4, y = 0.6, width = 0.5, height = 0.4,
   gp = gpar(col = "red", lwd = 2, fill = "yellow"), vp = vp1)

使用grid.circle函数画圆

grid.circle(x = 0.5, y = 0.5, r = 0.3,
  gp = gpar(lwd = 10, col = "blue", fill = "lightblue"))

三角形

使用grid.polygon函数画三角形

grid.polygon(x = c(0.1, 0.7, 0.8), y = c(0.2, 0.5, 0.8),
  gp = gpar(col = NA, fill = "pink"))

弧线

使用grid.curve函数画弧线,其中curvature表示曲率,ncp构成弧线的点的个数,越大弧线越平滑.

grid.curve(x1 = 0.1, y1 = 0.7, x2 = 0.6, y2 = 0.2,
   curvature = 0.15, square = FALSE, ncp = 30,
   gp = gpar(lwd = 10, col = "navyblue"))

波浪线
#构造波浪线函数
gCurve function (expr, from, to, n = 101,                    gp = gpar(),                    default.units = "npc", vp = NULL,                    name = NULL, draw = TRUE, xname = "x", ...) {  sexpr if (is.name(sexpr)) {    expr else {    if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in%          all.vars(sexpr)))      stop(gettextf("'expr' must be a function, or a call or an expression
             containing '%s'"
, xname), domain = NA)      expr if (length(y) != length(x))    stop("'expr' did not evaluate to an object of length 'n'")  x T))/(max(x, na.rm = T) - min(x, na.rm = T))  y T))/(max(y, na.rm = T) - min(y, na.rm = T))  grid.lines(x = x, y = y, default.units = default.units, gp = gp, vp = vp, ...)  invisible(list(x = x, y = y)) }
#绘制波浪线
gCurve(sin(x)/x, from = 0.1, to = 20, gp = gpar(lty = 3,lwd=2,col='red'))

十字图案
#定义函数
gCrissCross function(n = 5, gp = gpar(), vp = NULL, ...) {  x0 1, 0, 0.1)  ccGap 1, 0.3, 0.7)  y0 1, 0, 0.5)  for (i in 1:n) {    x0 1, 0.1, 0.2)    y0 1, -0.05, 0.05)    y1 1, -0.05, 0.05)    grid.segments(x0, y0, x0 + ccGap, y1, vp = vp, gp = gp, ...)    grid.segments(x0, y1, x0 + ccGap, y0, vp = vp, gp = gp, ...)  } }
#绘制十字图案
gCrissCross()

随机kandinsky抽象画

我们使用上面绘制的几何元素可以定制一副漂亮kandinsky抽象画

randomKandinsky function(n = 10) {  
#打开空白画板  grid.newpage()  
#对画板随机填充  grid.rect(gp=gpar(fill=rgb(runif(1),                             runif(1),                             runif(1),                             runif(1))))
 #绘制n个随机几何元素  for (i in 1:n) {    grid.rect(x = runif(1), y = runif(1), width = runif(1), height =runif(1),              gp = gpar(col = NA,                        fill=rgb(runif(1),                                 runif(1),                                 runif(1),                                 runif(1))))    grid.circle(x = runif(1), y = runif(1), r = runif(1),                gp = gpar(                  lwd = runif(1, 0, 100),                  col = rgb(runif(1),                            runif(1),                            runif(1),                            runif(1)),                  fill=rgb(runif(1),                           runif(1),                           runif(1),                           runif(1))))    grid.polygon(x = runif(3), y = runif(3),                 gp = gpar(col = NA,                           fill=rgb(runif(1),                                    runif(1),                                    runif(1),                                    runif(1))))    grid.curve(runif(1), runif(1), runif(1), runif(1),               curvature = runif(1, -1, 1), square = FALSE,               ncp =sample(100,1),gp = gpar(lwd = runif(1, 0, 10),                         col = rgb(runif(1),                                   runif(1),                                   runif(1),                                   1)))    vp1 1), y = runif(1), width = runif(1), height = runif(1), angle = runif(1) * 360)    grid.rect(x = runif(1), y = runif(1), width = runif(1), height =   runif(1),vp = vp1,              gp = gpar(col = NA,                        fill=rgb(runif(1),                                 runif(1),                                 runif(1),                                 runif(1))))    vp2 1), y = runif(1), width = runif(1), height = runif(1), angle = runif(1) * 360)    gCurve(sin(x)/(x), sample(5, 1), sample(10:50, 1), vp = vp2,           gp = gpar(lwd = runif(1, 0, 10),                     col = rgb(runif(1),                               runif(1),                               runif(1),                               1)))  }  vp3 1), y = runif(1), width = runif(1), height = runif(1), clip = "off")  gCrissCross(vp = vp3,              gp = gpar(lwd = runif(1, 0, 10),                        col = rgb(runif(1),                                  runif(1),                                  runif(1),                                  1))) } randomKandinsky(10)

randomKandinsky(1000)

绘制数据集

绘制数据集的主要思路是按列把数据集标准化(及变为0-1之间的元素), 数值型变量直接标准化,字符型因子型变量先变为数值型再标准化, 缺失值直接赋值给0.5.

#转换函数
zeroOneNormalize function(x) {  if (!is.numeric(x)) {    if (is.factor(x)) {      x else {      x if (length(unique(x)) == 1) {    return(rep(0.5, length(x)))  } else {    x TRUE)) /      (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))    x[is.na(x)] 0.5    return(x)  } }#绘图函数
kandinsky function(df = NULL, rv = runif(1000)) {  library(grid)  library(purrr)  if (!is.null(df)) {   rv 0  grid.rect(gp = gpar(fill = rgb(nex(rv), nex(rv), nex(rv), nex(rv))))  nRectangles 10) + 3  nCircles 10) + 3  nTriangles 10) + 3  nArchs 10) + 3  nTiltedRectangles 10) + 3  nWaves 10) + 3  nCrissCross 3) + 1  walk(1:nRectangles, drawRectangle, rv)  walk(1:nCircles, drawCircle, rv)  walk(1:nTriangles, drawTriangle, rv)  walk(1:nArchs, drawArch, rv)  walk(1:nTiltedRectangles, drawTiltedRectangle, rv)  walk(1:nWaves, drawWave, rv)  walk(1:nCrissCross, drawCrissCross, rv) }
#mtcars的kandinsky画
kandinsky(mtcars)

kandinsky(iris)



欢迎关注图表绘制之魔方学院QQ群