Bu grafik için bir isim var mı - bir pasta grafik ve bir mekko arsası arasında bir haç


9

Aşağıda bu tür bir grafik için bir isim var mı ( çalıştığım Yeni Zelanda İşletme, Yenilik ve İstihdam Bakanlığı'ndan alınmış , ancak bu arsa oluşturmakla ilgilenmedim)? Alanın bir değişkenle orantılı olduğu dikdörtgenlerden oluşur ve bir pasta grafik, mozaik bir arsa ve bir mekko arsası arasında bir tür çaprazlamaya benzer. Belki de bir mekko planına en yakın olanıdır, ancak sütunlarla değil daha karmaşık bir yapbozla çalıştığımız karmaşıklığına sahiptir.

Her bölge için dikdörtgenler arasında beyaz kenarlıklar olduğu için orijinal biraz daha iyi görünüyor.

Şaşırtıcı bir şekilde, bana istatistiksel bir grafik çok kötü değil gibi geliyor, ancak anlamlı bir şeye eşlenmiş renklerin daha iyi kullanılmasıyla geliştirilebilir. ABD 2011 bütçesini gösteren güçlü bir interaktif versiyon New York Times tarafından kullanılmıştır .

İlginç bir zorluk, bir tane çizmek ve makul görünmesini sağlamak için otomatik bir algoritma düşünmektir. Dikdörtgenlerin kabul edilebilir bir aralık içinde farklı en boy oranlarına sahip olmasına izin verilmelidir.

resim açıklamasını buraya girin


Bu soru ile başlayan projenin sonucu, buradan bağlantılı etkileşimli web aracında görülebilir: mbie.govt.nz/what-we-do/business-growth-agenda/regions
Peter Ellis

Yanıtlar:



12

Soru adı, ancak ne kadar iyi çalıştığı da tartışmaya açık.

İşte alternatif, yatay çubuk grafik olarak çok daha prosaik bir şey.

resim açıklamasını buraya girin

Böyle bir grafikle yapmak isteyebileceğimiz şey, genel paternin bazı kavrayışından bireysel vakaların bazı incelemelerine (Hawke Körfezi vb. Hakkında) değişir. Bir çubuk grafikle her ikisinin de daha kolay olduğunu iddia ediyorum. Küçük ayrıntılar, kolay olduğu yerlerde başlıklarda ve adlarda küçük harf kullanmam ve% işaretini tekrarlamam. Ne anlama geldiğini bulmadan kabaca renk kodlamasını taklit ettim, bu da kopyaladığınız kadar net veya belirsiz.

Treemapslerin cazibesinin bir kısmının göreceli yeniliklerinde yattığını öneriyorum. Uzun bir sütunda listelenmek yerine iki boyutlu bir alana yayılabilecek düzinelerce isim varsa, çubuk grafiklerden daha iyi veya daha iyi çalışabilirler. Ancak 15 kadar isim için, bir çubuk grafik bence güçlü bir rakip olmaya devam ediyor.

Burada (Cleveland) nokta grafiğini tercih eden herkesle mutluyum. Dikey bir çubuk grafik, bölge adlarını rahatça yerleştirme zorluğuyla karşı karşıya kalır. (Bunu görmek için sadece bu grafiği döndürdüğünüzü hayal edin.) Muhafazakarlar grafik ve tablo fikirlerini karıştırmayı sevmese de, sayıları da verme fikrini seviyorum.

Grafik Stata'da çizildi.


4
Kazmak zorunda kalacağım, ancak hafızam bana doğru bir şekilde hizmet ediyorsa, ağaç haritasının orijinal motivasyonlarından biri hiyerarşik bir bilgi organizasyonu içindi (yani, hiyerarşinin farklı düzeylerinin birleşik boyutunu görüntülemenize izin vermek için) ve daha fazla sayı için. Amaç hiçbir zaman küçük sayı listeleri için değildi ve daha keşifsel bir çekiciliği vardı, bkz. Dikdörtgen Treemaps Oluşturmak için Algısal Kılavuzlar ( Kong ve ark.2010 )
Andy W

1
Bu benim izlenimim, dolayısıyla treemap adı. Burada sadece bir hiyerarşi seviyesi açıktır.
Nick Cox

4
Bill Shneiderman, ilgili bazı yayınlara ( cs.umd.edu/hcil/treemap -history ) bağlantılar içeren güzel bir treemaps geçmişi hazırladı . Treemaps başlangıçta dendrogramlardan veya ağaçlardan daha az karmaşık bir hiyerarşi sergilemeyi amaçladı ve ilk başta sabit disklerin içeriğini görselleştirmek için kullanıldı. Günümüzde treemaplar, diğer uygulamaların yanı sıra büyük filogenetik ağaçların (türler arasındaki ilişkileri gösterir) görselleştirmek için kullanılmaktadır. Daha fazla örnek için de Shneiderman tarafından makalesine bakın perceptualedge.com/articles/b-eye/treemaps.pdf .
JTT

Teşekkürler; değer için bu özel durumda katılıyorum.
Peter Ellis

3

Düzenleme / ekleme

O zamandan beri treemap paketinin aşağıda belirtilen (ve uyarlanan) map.market () işlevinden çok daha iyi bir sonuç verdiğini keşfettim ; ama cevabımı tarihsel nedenlerle bırakacağım.

Orijinal Yanıt

Cevaplar için teşekkürler. @JTT tarafından sağlanan akan veri bağlantısını temel alarak, ancak makul bir grafik elde etmek için Illustrator veya Inkscape'te elle ince ayar yapmaya gerek duymadığından, daha fazlasını yapmak için Jeff Enos ve David Kane'in portföy paketinde map.market () işlevini değiştirdim kullanıcı tarafından kontrol edilen etiketler dikdörtgen boyutuna göre değişir ve kırmızı-yeşil kontrastlardan kaçınır. Örnek kullanım:

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")
    )

resim açıklamasını buraya girin

Değeri ne olursa olsun, orijinal sorumdaki örnekte bir nokta grafiğinin daha üstün olduğunu @NickCox ile de kabul ediyorum. Uyarlanmış treemap () fonksiyonumun kodu aşağıdadır.

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)
}

Bu kod şüphesiz faydalı olacaktır. Tartışmayı gitmeyeceği alanlara sürüklemek istemiyorum, ancak örnek oldukça keyfi mi yoksa alanların hisse senedi fiyatlarını temsil etmesine izin vermenin bir mantığı var mı? Bu arsada ne görmeli veya arıyoruz? (Ben düşmanca değilim, sadece bolca örnek
Nick Cox

1
Aslında Enos ve Kane'nin map.market () yardım dosyasından örnek aldım. Üzerinde yansıtarak neden alan gösterisi fiyat seçtiklerini görmüyorum; daha mantıklı bir önlem, toplam kapitalizasyonu göstermek olacaktır, yani fiyat x hisse sayısı (piyasadaki hisse sayısı veya sadece amaca bağlı olarak sahip olduğum hisse sayısı). Sonra farklı hisse senetlerinin önemini göstermek için arsa sezgisel bir kullanımı olacaktır.
Peter Ellis

Ben de fiyat kullanımı ile şaşkın.
Nick Cox

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.