2022年7月9日 星期六

馬賽克拼貼畫作與拼貼統計圖

 

像不像小磁磚拼貼而成的畫作?
 它不是小畫家做的,也不是Illustrator做的,
是由統計軟體SAS靠程式碼一格一格定位上色的。
程式碼撰寫者為SAS公司資歷超過25年的員工 Robert Allison。
SAS Code 如下:

%let name=pikachu_graph;
filename odsout '.';
data pika_map (drop = x_id y_id);
length id_var $10;
do x_id = 1 to 50; 
 do y_id = 1 to 55;
  id_var=trim(left(x_id))||'_'||trim(left(y_id));
  x=x_id-1; y=y_id-1; output; 
  x=x+1; output; 
  y=y+1; output; 
  x=x-1; output;
  end;
 end;
run;
data pika_data (drop = x_id y_id);
length rgb $6 color $8;
length id_var $10;
input x_id y_id rgb repeat;
 color='cx'||trim(left(rgb));
 do x = x_id to x_id+(repeat-1);
  id_var=trim(left(x))||'_'||trim(left(y_id));
  output;
  end;
datalines;
12 51 000000 1
11 50 000000 3
11 49 000000 3
11 48 000000 1
13 48 000000 2
10 47 000000 1
13 47 000000 2
37 47 000000 3
10 46 000000 1
14 46 000000 2
34 46 000000 3
39 46 000000 1
10 45 000000 1
14 45 ffc10e 1
15 45 000000 1
32 45 000000 2
38 45 000000 2
10 44 000000 1
13 44 fff100 2
15 44 000000 1
30 44 9c5a3c 1
31 44 ffc10e 1
36 44 000000 3
10 43 000000 2
12 43 fff100 3
15 43 ffc10e 1
16 43 000000 1
29 43 9b593b 1
30 43 fff100 2
35 43 000000 3
11 42 9b593b 1
12 42 fff100 3
15 42 ffc10e 1
16 42 000000 1
27 42 9b593b 1
28 42 ffc10e 1
29 42 fff100 4
34 42 000000 3
11 41 9b593b 1
12 41 ffc10e 1
13 41 fff100 1
14 41 ffc10e 2
16 41 000000 1
26 41 000000 1
27 41 fff100 6
33 41 ffc10e 1
34 41 000000 2
12 40 9b593b 1
13 40 ffc10e 3
16 40 000000 1
17 40 9b593b 2
19 40 ffc10e 3
22 40 9b593b 2
24 40 000000 2
26 40 fff100 5
31 40 ffc10e 2
33 40 000000 1
13 39 000000 1
14 39 ffc10e 1
15 39 9c593c 2
17 39 fff9bc 5
22 39 fff100 2
24 39 ffc10e 1
25 39 fff100 4
29 39 ffc10e 2
31 39 000000 2
43 39 9b593b 2
12 38 ffc10e 1
13 38 fff100 2
15 38 fff9bc 8
23 38 fff100 5
28 38 ffc10e 1
29 38 9b593b 1
30 38 000000 1
41 38 9b593b 1
42 38 ffc10e 1
43 38 fff9bc 1
44 38 fff100 1
45 38 000000 1
11 37 000000 1
12 37 fff100 3
15 37 fff9bc 8
23 37 fff100 5
28 37 ffc10e 1
29 37 9b593b 1
40 37 9b593b 1
41 37 fff9bc 1
42 37 fff100 3
45 37 000000 1
11 36 9b593b 1
12 36 ffc10e 1
13 36 000000 2
15 36 fff100 1
16 36 fff9bc 5
21 36 fff100 1
22 36 ffc10e 1
23 36 000000 2
25 36 ffc10e 1
26 36 fff100 2
28 36 ffc10e 2
30 36 000000 1
39 36 9c5a3c 1
40 36 fff9bc 1
41 36 fff100 3
44 36 ffc10e 1
45 36 000000 1
10 35 9b593b 1
11 35 fff100 1
12 35 000000 1
14 35 000000 1
15 35 fff100 7
22 35 000000 1
24 35 000000 2
26 35 fff100 2
28 35 ffc10e 2
30 35 000000 1
37 35 9b5a3c 1
38 35 ffc10e 1
39 35 fff9bc 1
40 35 fff100 2
42 35 ffc10e 4
46 35 000000 1
10 34 000000 1
11 34 fff100 1
12 34 000000 2
14 34 dbdbdb 1
15 34 fff100 7
22 34 000000 2
24 34 dbdbdb 1
25 34 000000 1
26 34 fff100 2
28 34 ffc10e 2
30 34 804000 1
36 34 9c5a3b 1
37 34 fff9bc 2
39 34 fff100 1
40 34 ffc10e 6
46 34 000000 1
 9 33 000000 1
10 33 ffc10e 1
11 33 fff100 1
12 33 9c5a3c 1
13 33 000000 1
14 33 ffc10e 1
15 33 fff100 2
17 33 000000 1
18 33 ffc10e 1
19 33 fff100 3
22 33 ffc10e 1
23 33 000000 2
25 33 ffc10e 1
26 33 fff100 3
29 33 ffc10e 2
31 33 000000 1
34 33 ffc10e 2
36 33 fff100 3
39 33 ffc10e 7
46 33 000000 1
 9 32 000000 1
10 32 ec1b23 1
11 32 fff100 4
15 32 ffc10e 1
16 32 fff100 5
21 32 9c5a3c 1
22 32 fff100 4
26 32 ec1b23 2
28 32 fff100 1
29 32 ffc10e 2
31 32 000000 1
32 32 804000 2
34 32 fff100 2
36 32 ffc10e 10
46 32 000000 1
 9 31 000000 1
10 31 ec1b23 1
11 31 ffc10e 1
12 31 fff100 4
16 31 9b593b 1
17 31 98002f 4
21 31 ffc10e 1
22 31 fff100 3
25 31 ec1b23 3
28 31 980030 1
29 31 ffc10e 1
30 31 804000 2
32 31 fff9bc 1
33 31 9c5a3c 1
34 31 804000 1
35 31 ffc10e 11
46 31 000000 1
 8 30 000000 1
10 30 000000 1
11 30 99002f 1
12 30 fff100 5
17 30 990030 2
19 30 fea2b0 2
21 30 fff100 4
25 30 ec1b23 3
28 30 990030 1
29 30 804000 1
30 30 fff9bc 1
31 30 9b593b 1
32 30 fff100 1
33 30 fff9bc 2
35 30 804000 1
36 30 ffc10e 10
46 30 000000 1
 7 29 000000 1
 8 29 fff9bc 1
 9 29 000000 2
11 29 990030 1
12 29 fff100 5
17 29 990030 1
18 29 fea2b0 2
20 29 990030 1
21 29 fff100 4
25 29 ec1b23 2
27 29 980030 1
28 29 ffc10e 1
29 29 980030 1
30 29 fff100 4
34 29 9b593b 1
35 29 804000 1
36 29 ffc10e 8
44 29 804000 1
45 29 000000 1
 6 28 000000 1
 7 28 fff9bc 1
 8 28 fff100 2
10 28 ffc10e 1
11 28 000000 1
12 28 fff100 6
18 28 98002f 2
20 28 fff100 6
26 28 98002f 1
27 28 ffc10e 1
28 28 804000 1
29 28 fff100 6
35 28 000000 1
36 28 ffc10e 6
42 28 804000 1
43 28 000000 1
 7 27 9c593b 1
 8 27 fff100 2
10 27 ffc10e 2
12 27 000000 1
13 27 fff100 14
27 27 804000 1
28 27 fff100 4
32 27 ffc10e 2
34 27 000000 1
35 27 ffc10e 5
40 27 804000 1
41 27 000000 1
 7 26 000000 1
 8 26 ffc10e 4
12 26 9c593b 2
14 26 fff100 17
31 26 ffc10e 3
34 26 000000 1
35 26 ffc10e 4
39 26 804000 1
 8 25 000000 1
 9 25 ffc10e 3
12 25 9b593b 1
13 25 fff100 17
30 25 ffc10e 3
33 25 000000 1
34 25 804000 1
35 25 ffc10e 3
38 25 000000 1
 9 24 000000 1
10 24 ffc10e 3
13 24 fff100 16
29 24 ffc10e 3
32 24 000000 1
35 24 804000 1
36 24 ffc10e 3
39 24 000000 1
10 23 000000 2
12 23 fff100 16
28 23 ffc10e 4
32 23 000000 1
36 23 804000 1
37 23 ffc10e 3
40 23 000000 1
11 22 9b593b 1
12 22 fff100 16
28 22 ffc10e 2
30 22 9c5a3b 1
31 22 804000 1
34 22 804000 2
36 22 ffc10e 5
41 22 000000 1
10 21 000000 1
11 21 fff100 17
28 21 ffc10e 1
29 21 9c593b 1
30 21 ffc10e 1
31 21 9c593b 1
32 21 000000 2
34 21 fff100 1
35 21 ffc10e 4
39 21 804000 1
40 21 000000 1
10 20 9c5a3c 1
11 20 fff100 17
28 20 ffc10e 3
31 20 804000 1
32 20 fff100 1
33 20 ffc10e 4
37 20 804000 1
38 20 000000 1
 9 19 000000 1
10 19 fff100 16
26 19 ffc10e 4
30 19 804000 1
31 19 ffc10e 4
35 19 000000 2
 8 18 000000 3
11 18 fff100 14
25 18 ffc10e 5
30 18 000000 1
31 18 ffc10e 3
34 18 000000 1
 7 17 000000 1
 8 17 fff9bc 2
10 17 9b5a3b 1
11 17 000000 1
12 17 fff100 13
25 17 ffc10e 5
30 17 000000 2
32 17 ffc10e 3
35 17 000000 1
 7 16 9c5a3c 2
 9 16 fff100 1
10 16 9c5a3c 1
11 16 fff100 1
12 16 000000 1
13 16 fff100 11
24 16 ffc10e 6 
30 16 000000 1 
32 16 000000 1 
33 16 ffc10e 3 
36 16 000000 1 
 7 15 000000 1
 8 15 ffc10e 4
12 15 9b593b 1
13 15 fff100 9
22 15 ffc10e 8
30 15 000000 2
32 15 804000 3
35 15 ffc10e 2
37 15 000000 1
 8 14 9b593b 1
 9 14 ffc10e 4
13 14 000000 1
14 14 ffc10e 2
16 14 fff100 4
20 14 ffc10e 10
30 14 804000 4
34 14 000000 3
 9 13 000000 1
10 13 ffc10e 3
13 13 000000 1
14 13 ffc10e 15
29 13 804000 2
31 13 000000 3
 9 12 000000 1
10 12 ffc10e 3
13 12 000000 1
14 12 ffc10e 15
29 12 000000 2
10 11 000000 3
13 11 ffc10e 15
28 11 9c5a3c 1
29 11 000000 1
13 10 000000 4
17 10 804000 1
18 10 9c5a3c 1
19 10 ffc10e 9
28 10 000000 1
18  9 000000 2
20  9 804000 1
21  9 ffc10e 6
27  9 000000 1
20  8 000000 2
22  8 9c593b 2
24  8 000000 3
20 7 804000 1
21 7 9c593c 4
25 7 000000 1
20 6 804000 1
21 6 9c593c 1
22 6 000000 1
23 6 9c593c 2
25 6 000000 1
20 5 804000 1
21 5 ffc10e 1
22 5 9c593c 1
23 5 ffc10e 1
24 5 000000 1
21 4 000000 3
;
run;
data anno_color; set pika_data;
xsys='2'; ysys='2'; hsys='3'; when='b';
length html $300;
html='title='||quote(trim(left(id_var))||'  '||trim(left(color)));
x_id=.; y_id=.;
x_id=scan(id_var,1,'_'); y_id=scan(id_var,2,'_');
function='move'; x=x_id-1; y=y_id-1; output;
function='bar'; style='solid'; x=x_id; y=y_id; output;
run;
goptions device=png;
goptions xpixels=650 ypixels=700;
goptions noborder;
ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm"
 (title="寶可夢-皮卡丘")
 style=htmlblue;
options nocenter;
goptions gunit=pct htitle=3.5 htext=2.0 ftitle="albany amt/bold" ftext="albany amt";
goptions ctext=gray33;
title1 ls=1.5 "寶可夢-皮卡丘";

pattern1 v=e c=pink repeat=2000;
proc gmap data=pika_data map=pika_map all anno=anno_color;
id id_var;
choro color / nolegend
 cdefault=white
 coutline=graycc
 des='' name="&name";
run;
quit;
ODS HTML CLOSE;
ODS LISTING;


對於這種「資料數據」拖很長的案例,你可以把數據另存成.sas檔或.xlsx檔,使用時,前者再以%include statement呼叫,後者則以Proc import重新匯入。這種極小量的數據寫程式不用考慮處理效能問題,它實際跑起來(4個階段全選一起跑)所花時間連1秒都不到。



關於這種馬賽克式或像素式的繪製方式,也可用 Proc IML先行將顏色位點標示於矩陣中(以下用名為A的矩陣將位置資訊包裏起來),再透過colorramp option指定顏色,但顏色如果有很多種,不建議用這種方式。

註:IML是一種結構化語言, 一旦資料庫資料轉成IML, 就可以寫出有結構化的程式。

Proc iml;
A = {1.0  0.2  0.0  0.0  0.0  0.0 2,
     0.2  1.0  0.2  0.0  0.0  0.0 0.0,
     0.0  0.2  1.0  0.2  0.0  0.0 0.0,
     0.0  0.0  0.2  1.0  0.2  0.0 0.0,
     2 0.0  0.0  0.2  1.0  0.2 0.0,
     3 1.2 0.0  0.0  0.2  1.0 0.2,
     5 1.1 1.2 0.0  0.0  0.2 1.0 };
ods graphics / width=400px height=400px;
call heatmapdisc(A^=0) colorramp={white green}
title="磁磚拼貼";

成品如下:



下圖把品質管理中心的簡稱QMC以魚的象形呈現。
格子愈小,圖一定會愈精細,但調整所耗時間當然會跟著拉長,語法如下。
proc iml;
A = {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
        0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
        0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
        0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 ,
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 ,
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 ,
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ,
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 ,
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 ,
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 ,
        0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ,
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 ,
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 ,
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 ,
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,
0 0 1 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 ,
0 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 1 0 0 ,
0 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 ,
0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 ,
0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 0 ,
0 0 1 0 0 0 0 1 0 0 1 0 0 1 1 0 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 ,
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 };

ods graphics / imagefmt=png width=800px height=800px;
call heatmapdisc(A^=0) colorramp={yellow  black};
quit;
ods graphics off;

第3種像素式畫作呈現方式,則融入年曆結構。下圖為數年前,我在職場常繪製的圖形。


這張圖呈現某個連續變項(我當然不能跟大家說上圖是什麼資料)在過往2013-2019年間每一日的數值變化。透過熱圖手法,清楚掌握這7年有哪些時間區間其值處於高峰階段(本圖不附SAS Code)。

沒有留言: