Racket Plot: Minamata Employment 1960

English Version of Employment Data Plot

(sort labels #:key row-sum >)

In Understanding Graphs and Tables Howard Wainer advises:

Order the rows and columns in a way that makes sense. We are almost never interested in “Austria First.” Two useful ways to order the data are:

a. Size places-Put the largest first. Often we look most carefully at what is on top and less carefully further down. Put the biggest thing first! Also, ordering by some aspect of the data often reflects ordering by some hidden variable that can be inferred. b. Naturally – Time is ordered from the past to the future. Showing data in that order melds well with what the viewer might expect. This is always a good idea.

— Howard Wainer (fn:1)

Howard Wainer's advice came to mind while working with data from a book about Minamata Disease (and pollution or Damage to the Commons in general).

Ui Jun's book and bsmall2's computer

The code to visualize Jun Ui's table of employment data is an attempt to implement Howard Wainer's advice (and general ink-to-data ratio advice for data visualization) with free software: DrRacket and Racket Plot.

Screenshot of Org-mode table in html with English version plot

As always, the code and data are below.

Here's proof that the code worked in DrRacket(6.7)

DrRacket Screenshot

code

#lang racket

;; racket/doc/style/Textual_Matters.html#%28part._names%29
;; Howard Wainer, Understanding Tables... : http://www.jstor.org/stable/1176346
(define my-home (find-system-path 'home-dir))
(define learning-directory "Learning-Minamata")

(define data-file "UiJun-SeijiGaku-SangyouJinkou-1.csv")
;; 産業大分類別,男,女
;; 農業,2139,3548
;; 林業・狩猟業,182,35
;; 漁業・水産・養殖業,132,27
;; 鉱業,40,2
;; 建設業,1197,366
;; 製造業,3854,613
;; 卸・小売業,1412,1562
;; 金融・保険・不動産業,162,73
;; 運輸・通信業,1074,186
;; 公益事業,76,7
;; サービス業,1287,1322
;; 公務,451,72

(current-directory-for-user (build-path my-home learning-directory))
(define data-path (build-path my-home learning-directory data-file))
(define get-data
  (lambda (pth)
    (let* ((inp (open-input-file pth))
	   (lines (port->lines inp)))
      (close-input-port inp)
      (map (lambda (s) (string-split
			(regexp-replace* "\"" s "")
				     ","))
	   lines))))

(define employment-data (get-data data-path))
(define headers (first employment-data))
(define employment-labels (rest employment-data))

(define (sum-row label-row)
  (apply + (map string->number (cdr label-row))))

  
(define (sum-columns labels)
  (define (keeper rows sums)
    (cond
     ((empty? rows) sums)
     (#t (keeper (cdr rows)
		 (map +
		      (map string->number (cdr (car rows)))
		      sums)))))
  (keeper labels (make-list
		  (length (cdr (car labels))) 0)))
(define (total-table labels)
  (apply + (sum-columns labels)))

(define (percentage-rows labels)
  (let ((total (total-table labels)))
    (define (percent-row label-row)
      (* 100.0 (/ (sum-row label-row) total)))
    (map percent-row labels)))

(require plot/utils)

(define (percent->label real)
  (real->decimal-string real 1))

(require plot)

(define horizontal-line
  (lambda (x y #:clr (clr "black")) ;; lne-wdh lne-stl ..etc
    (lines (list (vector 0 y) (vector x y)) #:color clr)))

(define labeled-point
  (lambda (x y l #:ancr (ancr 'left) #:fnt-sze (fnt-sze 8) #:pnt-sze (pnt-sze 5)
            #:pnt-clr (pnt-clr 0) #:lbl-angl (lbl-angl 0) )
    (point-label (vector x y) l #:anchor ancr #:size fnt-sze #:point-size pnt-sze
                #:point-color pnt-clr #:angle lbl-angl)))

(define labeled-horizontal-line
  (lambda (x y l #:clr (clr "black") #:ancr (ancr 'left) #:fnt-sze (fnt-sze 8) #:pnt-sze (pnt-sze 5)
            #:pnt-clr (pnt-clr 0) #:lbl-angl (lbl-angl 0))
    (list
     (horizontal-line x y #:clr clr)
     (labeled-point x y l #:ancr ancr  #:fnt-sze fnt-sze #:pnt-sze pnt-sze
            #:pnt-clr pnt-clr #:lbl-angl lbl-angl))))

(define (plot-a-field-line row n)
  (let* ((field-label (first row))
	 (field-offset -150)
	 (man-lab  (second row))
         (male "男")
	 (woman-lab (third row))
         (female "女")
	 (man-num (string->number man-lab))
	 (woman-num (string->number woman-lab))
	 (sum-num (sum-row row))
	 (sum-lab (number->string sum-num)))
    (list
     (labeled-point field-offset n field-label #:fnt-sze 10 #:ancr 'right #:pnt-sze 0)
     (labeled-horizontal-line sum-num n (string-append " " sum-lab "人") #:ancr 'left)
     (labeled-point woman-num n (string-append woman-lab female) #:ancr 'bottom-right #:pnt-clr "HotPink")
     (labeled-point sum-num n (string-append man-lab male) #:ancr 'bottom #:pnt-clr "DarkBlue"))))

(define (plot-percent-2ji row n table)
  (let* ((total (total-table table))
         (total-lab (number->string total))
         (row-sum (sum-row row))
         (row-sum-lab (number->string row-sum))
         (label-pad (string-append " "
                                (make-string (+ 1 (string-length row-sum-lab)) #\ )))
         (field2ji (substring (car row) 0 2))
         (field% (real->decimal-string
                  (* 100.0 (/ row-sum total)) 1))
         (row-percent-lab
          (string-append label-pad field% "%" field2ji)))
    (labeled-point row-sum n row-percent-lab #:ancr 'left #:fnt-sze 10 #:pnt-sze 0)))
        

(define (plot-fields label-rows)
  (define (helper rows y plots)
    (cond
      ((empty? rows) plots)
      (#t (helper (cdr rows) (add1 y)
                 (cons (plot-a-field-line (car rows) y)
                      (cons (plot-percent-2ji (car rows) y label-rows)
                      plots))))))
  (helper label-rows 0 '()))
  

(parameterize
    ((plot-title "宇井純「公害の政治学」p21 第4表 水俣市産業人口1960l")
     (plot-x-axis? #f)
     (plot-x-label #f)
     (plot-x-far-axis? #f)
     (plot-y-axis? #f)
     (plot-y-label #f)
     (plot-y-far-axis? #f)
     (plot-width 900)
     (plot-height 500)
     )
  (plot
   ;(plot-a-field-line (second employment-labels) 2)
   (plot-fields (sort employment-labels #:key sum-row >))
   
   #:x-min -1500 #:x-max 6800
   #:y-min -1 #:y-max  (length employment-labels)
   #:out-file "UiJun-Employment1960-2.png"
   #:out-kind 'png

   ))

(define work-fields-en '("farming" "forestry" "fishery" "mining" "building" "making" "selling" "money" "transport" "public" "service" "goverment"))
(define replace-firsts
  (lambda (orig-list new-firsts)
    (define replace-first  ;; Racket-style guide "lambda is cute but..."
      (lambda (lst frst)
        (cons frst (rest lst))))
    (map replace-first orig-list new-firsts)))
(define en-employment-labels (replace-firsts employment-labels work-fields-en))

(define (en-plot-a-field-line row n)
  (let* ((field-label (first row))
	 (field-offset -150)
	 (man-lab  (second row))
         (male "M")
	 (woman-lab (third row))
         (female "W")
	 (man-num (string->number man-lab))
	 (woman-num (string->number woman-lab))
	 (sum-num (sum-row row))
	 (sum-lab (number->string sum-num)))
    (list
     (labeled-point field-offset n field-label #:fnt-sze 10 #:ancr 'right #:pnt-sze 0)
     (labeled-horizontal-line sum-num n (string-append " " sum-lab "P") #:ancr 'left)
     (labeled-point woman-num n (string-append woman-lab female) #:ancr 'bottom-right #:pnt-clr "HotPink")
     (labeled-point sum-num n (string-append man-lab male) #:ancr 'bottom #:pnt-clr "DarkBlue"))))

(define (en-plot-percent-2ji row n table)
  (let* ((total (total-table table))
         (total-lab (number->string total))
         (row-sum (sum-row row))
         (row-sum-lab (number->string row-sum))
         (label-pad (string-append "    "
                                (make-string (+ 1 (string-length row-sum-lab)) #\ )))
         (field2ji (substring (car row) 0 4))
         (field% (real->decimal-string
                  (* 100.0 (/ row-sum total)) 1))
         (row-percent-lab
          (string-append label-pad field% "%" field2ji)))
    (labeled-point row-sum n row-percent-lab #:ancr 'left #:fnt-sze 10 #:pnt-sze 0)))


(define (en-plot-fields label-rows)
  (define (helper rows y plots)
    (cond
      ((empty? rows) plots)
      (#t (helper (cdr rows) (add1 y)
                 (cons (en-plot-a-field-line (car rows) y)
                      (cons (en-plot-percent-2ji (car rows) y label-rows)
                      plots))))))
  (helper label-rows 0 '()))

(parameterize
    ((plot-title "Jun Ui _Politics of Commons Damage_ p21 Table4 Minamata1960")
     (plot-x-axis? #f)
     (plot-x-label #f)
     (plot-x-far-axis? #f)
     (plot-y-axis? #f)
     (plot-y-label #f)
     (plot-y-far-axis? #f)
     (plot-width 900)
     (plot-height 500)
     )
  (plot
   ;(plot-a-field-line (second employment-labels) 2)
   (en-plot-fields (sort en-employment-labels #:key sum-row >))
   
   #:x-min -1500 #:x-max 6800
   #:y-min -1 #:y-max  (length employment-labels)
   #:out-file "UiJun-Employment1960-2-en.png"
   #:out-kind 'png

   ))

Minamata 1960 Employment Data Japanese Version

#DrRacket #DataVisualization #Manamata #JunUi #UiJUn #宇井純 #水俣 #公害 #HowardWainer