Apakah ada nama untuk bagan ini - semacam persilangan antara bagan pai dan plot mekko

9

Apakah ada nama untuk jenis bagan di bawah ini (bersumber dari Kementerian Bisnis, Inovasi, dan Ketenagakerjaan Selandia Baru , untuk siapa saya bekerja tetapi saya tidak terlibat dalam membuat plot ini)? Ini terdiri dari empat persegi panjang di mana area proporsional dengan variabel, dan menyerupai semacam persilangan antara diagram lingkaran, plot mosaik dan plot mekko. Ini mungkin paling dekat dengan plot mekko tetapi memiliki kerumitan bahwa kita tidak bekerja dengan kolom tetapi teka-teki yang lebih kompleks.

Dokumen asli terlihat sedikit lebih baik karena ada batas putih antara persegi panjang untuk setiap wilayah.

Anehnya, itu benar-benar menurut saya grafik grafis yang tidak terlalu buruk, meskipun itu dapat ditingkatkan melalui penggunaan warna yang lebih baik untuk sesuatu yang bermakna. Versi interaktif yang tangguh yang menunjukkan anggaran AS 2011 telah digunakan oleh New York Times .

Tantangan yang menarik adalah memikirkan algoritma otomatis untuk menggambar satu dan membuatnya terlihat masuk akal juga. Persegi panjang harus diizinkan untuk memiliki rasio aspek yang berbeda, dalam rentang yang dapat diterima.

masukkan deskripsi gambar di sini

Peter Ellis
sumber
Hasil akhir dari proyek yang dimulai dengan pertanyaan ini dapat dilihat di alat web interaktif yang ditautkan dari sini: mbie.govt.nz/what-we-do/business-growth-agenda/regions
Peter Ellis

Jawaban:

12

Pertanyaannya adalah nama, tetapi seberapa baik kerjanya juga terbuka untuk diskusi.

Berikut ini sesuatu yang jauh lebih sederhana sebagai alternatif, bagan batang horizontal.

masukkan deskripsi gambar di sini

Apa yang mungkin ingin kita lakukan dengan grafik semacam itu bervariasi dari beberapa pemahaman pola keseluruhan hingga beberapa penelitian kasus individu (bagaimana dengan Teluk Hawke, dan sebagainya). Saya akan menegaskan bahwa keduanya lebih mudah dengan grafik batang. Detail kecilnya adalah saya menggunakan huruf kecil pada judul dan nama yang mudah dan tidak mengulangi tanda%. Saya secara kasar meniru kode warna tanpa mencari tahu apa artinya, sehingga sama jelasnya, atau tidak jelas, seperti apa yang Anda salin.

Saya menyarankan bahwa beberapa daya tarik treemaps terletak pada kebaruan relatif mereka. Mereka mungkin bekerja sebaik atau lebih baik daripada diagram batang jika ada lusinan nama, yang dapat tersebar di area dua dimensi daripada terdaftar dalam kolom panjang. Tetapi untuk 15 atau lebih nama, bagan batang tetap menjadi pesaing yang kuat dalam pandangan saya.

Saya senang dengan siapa saja yang lebih suka grafik titik (Cleveland) di sini. Bagan batang vertikal akan menghadapi kesulitan menempatkan nama wilayah dengan nyaman. (Bayangkan saja memutar grafik ini untuk melihat itu.) Saya suka ide memberikan angka juga, meskipun konservatif tidak suka mencampur grafik dan ide-ide tabel.

Grafik digambar di Stata.

Nick Cox
sumber
4
Saya harus menggali, tetapi jika ingatan saya benar, salah satu motivasi asli dari peta pohon adalah untuk organisasi informasi hierarkis (yaitu untuk memungkinkan Anda melihat ukuran gabungan berbagai tingkat hierarki) dan untuk lebih banyak nomor. Maksudnya tidak pernah untuk daftar angka kecil dan memiliki daya tarik yang lebih eksploratif, lihat Pedoman Perseptual untuk Membuat Treemaps Persegi Panjang ( Kong et al. 2010 )
Andy W
1
Itu kesan saya juga, karena itu namanya treemap. Hanya satu tingkat hierarki yang jelas di sini.
Nick Cox
4
Bill Shneiderman telah menyusun sejarah treemaps yang bagus dengan tautan ke beberapa publikasi yang relevan ( cs.umd.edu/hcil/treemap-history ). Treemaps pada awalnya dimaksudkan untuk menampilkan hierarki bertingkat dengan cara yang kurang berantakan daripada dendrogram atau pohon, dan pada awalnya digunakan untuk memvisualisasikan isi hard disk. Saat ini, treemaps digunakan untuk memvisualisasikan pohon filogenetik besar (mereka menunjukkan hubungan antar spesies), di antara aplikasi lain. Untuk contoh lebih lanjut, lihat artikel oleh Shneiderman di perceptualedge.com/articles/b-eye/treemaps.pdf .
JTT
Terima kasih; untuk apa nilainya saya setuju dalam kasus khusus ini.
Peter Ellis
3

Edit / penambahan

Saya telah menemukan bahwa paket treemap memberikan hasil yang jauh lebih baik daripada fungsi map.market () yang disebutkan (dan diadaptasi) di bawah ini; tetapi saya akan meninggalkan jawaban saya karena alasan historis.

Jawaban Asli

Terima kasih atas jawabannya. Membangun pada tautan data mengalir yang disediakan oleh @JTT tetapi tidak menyukai kebutuhan untuk mengubah dengan tangan di Illustrator atau Inkscape hanya untuk mendapatkan grafik yang masuk akal, saya mengubah fungsi map.market () dalam paket portofolio Jeff Enos dan David Kane untuk membuatnya lebih dikontrol oleh pengguna, label bervariasi menurut ukuran persegi panjang, dan menghindari kontras merah-hijau. Contoh penggunaan:

library(portfolio)
library(extrafont)
data(dow.jan.2005)

with(dow.jan.2005, 
    treemap(id    = symbol,
        area  = price,
        group = sector,
        color = 100 * month.ret,
        labsc = .12,  # user-chosen scaling of labels 
        fontfamily="Comic Sans MS")
    )

masukkan deskripsi gambar di sini

Untuk apa nilainya, saya juga setuju dengan @NickCox bahwa dalam contoh di pertanyaan awal saya, dot plot lebih unggul. Kode fungsi treemap () saya yang diadaptasi mengikuti.

treemap <- function (id, area, group, color, scale = NULL, lab = c(group = TRUE, 
    id = FALSE), low="red", middle="grey60", high="blue", main = "Map of the Market", labsc = c(.5, 1), print = TRUE, ...) 
{
    # Adapted by Peter Ellis from map.market() by Jeff Enos and David Kane in the portfolio package on CRAN
    # See map.market for the original helpfile.  The changes are:
    # 1. low, middle and high are user-set color ramp choices
    # 2. The font size now varies with the area of the rectangle being labelled; labsc is a scaling parameter to make it look ok.
    #    First element of labsc is scaling parameter for size of group labels.  Second element is scaling for id labels.
    # 3. ... extra arguments to be passed to gpar() when drawing labels; expected use is for fontfamily="whatever"
    require(portfolio)
    if (any(length(id) != length(area), length(id) != length(group), 
        length(id) != length(color))) {
        stop("id, area, group, and color must be the same length.")
    }
    if (length(lab) == 1) {
        lab[2] <- lab[1]
    }
    if (missing(id)) {
        id <- seq_along(area)
        lab["id"] <- FALSE
    }
    stopifnot(all(!is.na(id)))
    data <- data.frame(label = id, group, area, color)
    data <- data[order(data$area, decreasing = TRUE), ]
    na.idx <- which(is.na(data$area) | is.na(data$group) | is.na(data$color))
    if (length(na.idx)) {
        warning("Stocks with NAs for area, group, or color will not be shown")
        data <- data[-na.idx, ]
    }
    zero.area.idx <- which(data$area == 0)
    if (length(zero.area.idx)) {
        data <- data[-zero.area.idx, ]
    }
    if (nrow(data) == 0) {
        stop("No records to display")
    }
    data$color.orig <- data$color
    if (is.null(scale)) {
        data$color <- data$color * 1/max(abs(data$color))
    }
    else {
        data$color <- sapply(data$color, function(x) {
            if (x/scale > 1) 
                1
            else if (-1 > x/scale) 
                -1
            else x/scale
        })
    }
    data.by.group <- split(data, data$group, drop = TRUE)
    group.data <- lapply(data.by.group, function(x) {
        sum(x[, 3])
    })
    group.data <- data.frame(area = as.numeric(group.data), label = names(group.data))
    group.data <- group.data[order(group.data$area, decreasing = TRUE), 
        ]
    group.data$color <- rep(NULL, nrow(group.data))
    color.ramp.pos <- colorRamp(c(middle, high))
    color.ramp.neg <- colorRamp(c(middle, low))
    color.ramp.rgb <- function(x) {
        col.mat <- mapply(function(x) {
            if (x < 0) {
                color.ramp.neg(abs(x))
            }
            else {
                color.ramp.pos(abs(x))
            }
        }, x)
        mapply(rgb, col.mat[1, ], col.mat[2, ], col.mat[3, ], 
            max = 255)
    }
    add.viewport <- function(z, label, color, x.0, y.0, x.1, 
        y.1) {
        for (i in 1:length(label)) {
            if (is.null(color[i])) {
                filler <- gpar(col = "blue", fill = "transparent", 
                  cex = 1)
            }
            else {
                filler.col <- color.ramp.rgb(color[i])
                filler <- gpar(col = filler.col, fill = filler.col, 
                  cex = 0.6)
            }
            new.viewport <- viewport(x = x.0[i], y = y.0[i], 
                width = (x.1[i] - x.0[i]), height = (y.1[i] - 
                  y.0[i]), default.units = "npc", just = c("left", 
                  "bottom"), name = as.character(label[i]), clip = "on", 
                gp = filler)
            z <- append(z, list(new.viewport))
        }
        z
    }
    squarified.treemap <- function(z, x = 0, y = 0, w = 1, h = 1, 
        func = add.viewport, viewport.list) {
        cz <- cumsum(z$area)/sum(z$area)
        n <- which.min(abs(log(max(w/h, h/w) * sum(z$area) * 
            ((cz^2)/z$area))))
        more <- n < length(z$area)
        a <- c(0, cz[1:n])/cz[n]
        if (h > w) {
            viewport.list <- func(viewport.list, z$label[1:n], 
                z$color[1:n], x + w * a[1:(length(a) - 1)], rep(y, 
                  n), x + w * a[-1], rep(y + h * cz[n], n))
            if (more) {
                viewport.list <- Recall(z[-(1:n), ], x, y + h * 
                  cz[n], w, h * (1 - cz[n]), func, viewport.list)
            }
        }
        else {
            viewport.list <- func(viewport.list, z$label[1:n], 
                z$color[1:n], rep(x, n), y + h * a[1:(length(a) - 
                  1)], rep(x + w * cz[n], n), y + h * a[-1])
            if (more) {
                viewport.list <- Recall(z[-(1:n), ], x + w * 
                  cz[n], y, w * (1 - cz[n]), h, func, viewport.list)
            }
        }
        viewport.list
    }
    map.viewport <- viewport(x = 0.05, y = 0.05, width = 0.9, 
        height = 0.75, default.units = "npc", name = "MAP", just = c("left", 
            "bottom"))
    map.tree <- gTree(vp = map.viewport, name = "MAP", children = gList(rectGrob(gp = gpar(col = "dark grey"), 
        name = "background")))
    group.viewports <- squarified.treemap(z = group.data, viewport.list = list())
    for (i in 1:length(group.viewports)) {
        this.group <- data.by.group[[group.data$label[i]]]
        this.data <- data.frame(this.group$area, this.group$label, 
            this.group$color)
        names(this.data) <- c("area", "label", "color")
        stock.viewports <- squarified.treemap(z = this.data, 
            viewport.list = list())
        group.tree <- gTree(vp = group.viewports[[i]], name = group.data$label[i])
        for (s in 1:length(stock.viewports)) {
            stock.tree <- gTree(vp = stock.viewports[[s]], name = this.data$label[s], 
                children = gList(rectGrob(name = "color")))
            if (lab[2]) {
                stock.tree <- addGrob(stock.tree, textGrob(x = unit(1, 
                  "lines"), y = unit(1, "npc") - unit(1, "lines"), 
                  label = this.data$label[s], gp = gpar(col = "white", fontsize=this.data$area[s] * labsc[2], ...), 
                  name = "label", just = c("left", "top")))
            }
            group.tree <- addGrob(group.tree, stock.tree)
        }
        group.tree <- addGrob(group.tree, rectGrob(gp = gpar(col = "grey"), 
            name = "border"))
        if (lab[1]) {
            group.tree <- addGrob(group.tree, textGrob(label = group.data$label[i], 
                name = "label", gp = gpar(col = "white", fontsize=group.data$area[i] * labsc[1], ...)))
        }
        map.tree <- addGrob(map.tree, group.tree)
    }
    op <- options(digits = 1)
    top.viewport <- viewport(x = 0.05, y = 1, width = 0.9, height = 0.2, 
        default.units = "npc", name = "TOP", , just = c("left", 
            "top"))
    legend.ncols <- 51
    l.x <- (0:(legend.ncols - 1))/(legend.ncols)
    l.y <- unit(0.25, "npc")
    l.cols <- color.ramp.rgb(seq(-1, 1, by = 2/(legend.ncols - 
        1)))
    if (is.null(scale)) {
        l.end <- max(abs(data$color.orig))
    }
    else {
        l.end <- scale
    }
    top.list <- gList(textGrob(label = main, y = unit(0.7, "npc"), 
        just = c("center", "center"), gp = gpar(cex = 2, ...)), segmentsGrob(x0 = seq(0, 
        1, by = 0.25), y0 = unit(0.25, "npc"), x1 = seq(0, 1, 
        by = 0.25), y1 = unit(0.2, "npc")), rectGrob(x = l.x, 
        y = l.y, width = 1/legend.ncols, height = unit(1, "lines"), 
        just = c("left", "bottom"), gp = gpar(col = NA, fill = l.cols), 
        default.units = "npc"), textGrob(label = format(l.end * 
        seq(-1, 1, by = 0.5), trim = TRUE), x = seq(0, 1, by = 0.25), 
        y = 0.1, default.units = "npc", just = c("center", "center"), 
        gp = gpar(col = "black", cex = 0.8, fontface = "bold")))
    options(op)
    top.tree <- gTree(vp = top.viewport, name = "TOP", children = top.list)
    mapmarket <- gTree(name = "MAPMARKET", children = gList(rectGrob(gp = gpar(col = "dark grey", 
        fill = "dark grey"), name = "background"), top.tree, 
        map.tree))
    if (print) {
        grid.newpage()
        grid.draw(mapmarket)
    }
    invisible(mapmarket)
}
Peter Ellis
sumber
Kode itu pasti akan berguna. Saya tidak ingin menyeret diskusi ke daerah-daerah di mana itu tidak akan pergi, tetapi apakah contohnya cukup sewenang-wenang atau apakah ada alasan untuk membiarkan daerah mewakili harga saham? Apa yang seharusnya kita lihat atau cari di plot ini? (Saya tidak bermusuhan, hanya benar-benar tidak berpengalaman dalam mencoba menggunakan desain ini secara nyata, walaupun saya telah melihat banyak contoh.)
Nick Cox
1
Sebenarnya saya hanya mengambil contoh itu dari file bantuan untuk map.market () oleh Enos dan Kane. Merefleksikannya saya tidak melihat mengapa mereka memilih untuk memiliki harga area show; ukuran yang lebih masuk akal akan menunjukkan total kapitalisasi yaitu harga x jumlah saham (baik jumlah saham di pasar, atau hanya jumlah saham yang kebetulan saya miliki tergantung pada tujuannya). Maka Anda akan memiliki penggunaan plot yang intuitif untuk menunjukkan pentingnya stok yang berbeda.
Peter Ellis
Saya juga bingung dengan penggunaan harga.
Nick Cox
1

Ini adalah treemap, Anda dapat melakukannya dengan mudah dengan Tableau 8 dan Tableau Public gratis, lihat contoh di sini: http://www.tableausoftware.com/new-features/new-view-types . Anda juga dapat melihat @ URL ini yang dapat dikombinasikan oleh Treemap dengan Bar Chart

Andrew Pandre
sumber