Ist es möglich, mit R „parallele Mengen“ zu zeichnen?


16

Dank der Tormod-Frage ( hier gepostet ) bin ich auf den Plot Parallel Sets gestoßen. Hier ist ein Beispiel dafür, wie es aussieht: Bildbeschreibung hier eingeben (Es ist eine Visualisierung des Titanic-Datensatzes. Zeigt zum Beispiel, wie die meisten Frauen, die nicht überlebt haben, zur dritten Klasse gehörten ...)

Ich würde gerne in der Lage sein, eine solche Handlung mit R zu reproduzieren. Ist das möglich?

Danke, Tal


1
Für Ideen zu Grafiken überprüfe ich immer die R-Grafikgalerie. Hier ist etwas von dort, das ungefähr so ​​ist, wie Sie es wünschen: R Graph Gallery parallel . Ich habe es gefunden, indem ich parallel in die Tag-Cloud geklickt habe, aber es gibt möglicherweise bessere Optionen.
Nick Sabbe

1
Danke Nick. Dies funktioniert jedoch nicht für kategoriale Daten, ohne den Code wesentlich zu optimieren (dies ist wahrscheinlich auch nicht die beste Basis für Funktionen, mit denen dies erstellt werden kann). Ich hoffe, jemand könnte schon etwas Ähnliches getan haben ...
Tal Galili

Antworten:


25

Hier ist eine Version, die dank Hadleys Kommentar nur Basisgrafiken verwendet. (Informationen zur vorherigen Version finden Sie unter Verlauf bearbeiten.)

Dritter Versuch

parallelset <- function(..., freq, col="gray", border=0, layer, 
                             alpha=0.5, gap.width=0.05) {
  p <- data.frame(..., freq, col, border, alpha, stringsAsFactors=FALSE)
  n <- nrow(p)
  if(missing(layer)) { layer <- 1:n }
  p$layer <- layer
  np <- ncol(p) - 5
  d <- p[ , 1:np, drop=FALSE]
  p <- p[ , -c(1:np), drop=FALSE]
  p$freq <- with(p, freq/sum(freq))
  col <- col2rgb(p$col, alpha=TRUE)
  if(!identical(alpha, FALSE)) { col["alpha", ] <- p$alpha*256 }
  p$col <- apply(col, 2, function(x) do.call(rgb, c(as.list(x), maxColorValue = 256)))
  getp <- function(i, d, f, w=gap.width) {
    a <- c(i, (1:ncol(d))[-i])
    o <- do.call(order, d[a])
    x <- c(0, cumsum(f[o])) * (1-w)
    x <- cbind(x[-length(x)], x[-1])
    gap <- cumsum( c(0L, diff(as.numeric(d[o,i])) != 0) )
    gap <- gap / max(gap) * w
    (x + gap)[order(o),]
  }
  dd <- lapply(seq_along(d), getp, d=d, f=p$freq)
  par(mar = c(0, 0, 2, 0) + 0.1, xpd=TRUE )
  plot(NULL, type="n",xlim=c(0, 1), ylim=c(np, 1),
       xaxt="n", yaxt="n", xaxs="i", yaxs="i", xlab='', ylab='', frame=FALSE)
  for(i in rev(order(p$layer)) ) {
     for(j in 1:(np-1) )
     polygon(c(dd[[j]][i,], rev(dd[[j+1]][i,])), c(j, j, j+1, j+1),
             col=p$col[i], border=p$border[i])
   }
   text(0, seq_along(dd), labels=names(d), adj=c(0,-2), font=2)
   for(j in seq_along(dd)) {
     ax <- lapply(split(dd[[j]], d[,j]), range)
     for(k in seq_along(ax)) {
       lines(ax[[k]], c(j, j))
       text(ax[[k]][1], j, labels=names(ax)[k], adj=c(0, -0.25))
     }
   }           
}

data(Titanic)
myt <- subset(as.data.frame(Titanic), Age=="Adult", 
              select=c("Survived","Sex","Class","Freq"))
myt <- within(myt, {
  Survived <- factor(Survived, levels=c("Yes","No"))
  levels(Class) <- c(paste(c("First", "Second", "Third"), "Class"), "Crew")
  color <- ifelse(Survived=="Yes","#008888","#330066")
})

with(myt, parallelset(Survived, Sex, Class, freq=Freq, col=color, alpha=0.2))

Aaron, wow, fantastische Antwort - ich wünschte, ich könnte es zweimal markieren. Vielen Dank!
Tal Galili

2
Froh, dass Sie es mögen. Es hat Spaß gemacht. :) Der einzige schwierige Teil ist, die Stellen zu finden, an denen die Balken beginnen und enden sollen (was in der getpUnterfunktion enthalten ist). der Rest ist nur das Zeichnen von Polygonen.
Aaron - Reinstate Monica

1
Nur eine weitere panel.textZeile. Siehe Bearbeiten.
Aaron - Reinstate Monica

1
Sie können Transparenz auch in Basisgrafiken machen.
Hadley

2
Du hast Recht. Das hatte ich völlig vergessen, weil ich mich so an die Art und Weise gewöhnt hatte, Dinge zu tun. Für andere, die interessiert sind, fügen Sie Ihrer Farbzeichenfolge beispielsweise ein paar weitere Zeichen hinzu #FF000080. ?rgbhat Details.
Aaron - Reinstate Monica

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.