2016-05-30 10 views
3

Der folgende Code erstellt eine Choroplethenkarte nach hierarchischem Clustering (mit hclust() und cutree()):r: Choropleth mit maßgeschneiderter Legende und permanenter Anzeige der Ländernamen

library(plotly) 
library(cluster) 

hc <- hclust(dist(df), method = "complete") 
df$member <- cutree(hc, 5) 

cluster.means = (as.data.frame(aggregate(df[,-1], list(cluster= df$member), mean)))[,-4] 

g = list(
    scope = 'africa', 
    showframe = T, 
    showland = T, 
    landcolor = toRGB("white") 
) 

plot_ly(df, z = member, type = 'choropleth', locations = Country, 
       locationmode = 'country names', text = Country, hoverinfo = "text") %>% 
     layout(geo = g, title = "Energy markets in Africa") 

Nun möchte Ich mag zwei Dinge ändern:

  1. Permanent Anzeige der Ländernamen, dh nicht nur beim Schweben über die interaktive Tabelle in RStudio. Ich habe versucht, die Antwort von this post auf meine zu übertragen, ohne Erfolg.
  2. Eine nicht kontinuierliche Skala. Idealerweise hätte ich gerne keine Skalierung, ABER 5 Boxen für je einen Cluster mit folgenden drei Eigenschaften: (1) Die Farbe der Box sollte entsprechend der jeweiligen Farbe in der Choropleth (2) sein. Jede Box sollte enthalten die Anzahl der Länder, ihm zugeordneten, also dem jeweiligen Cluster (3) sollte Jeder Kasten das entsprechende Cluster enthalten Mittel für die beiden Variablen (X1, X2), die in cluster.means

enthalten sind I gebunden haben einen solchen Beispielhafte Handlung dessen, was ich vorhabe (es muss nicht genau gleich aussehen - nur um die Idee zu vermitteln).

An exemplary choroplot containing only 2, instead of 5 boxes

Jede Hilfe, Beratung, ist tipp sehr geschätzt!

(Scaled) Daten sieht wie folgt aus:

df <- structure(list(Country = structure(1:50, .Label = c("Angola", 
"Benin", "Botswana", "Burkina Faso", "Burundi", "Cabo Verde", 
"Cameroon", "Central African Republic", "Chad", "Comoros", "Congo", 
"Cote d'Ivoire", "Democratic Republic of Congo", "Djibouti", 
"Equatorial Guinea", "Eritrea", "Ethiopia", "Gabon", "Gambia", 
"Ghana", "Guinea", "Guinea-Bissau", "Kenya", "Lesotho", "Liberia", 
"Madagascar", "Malawi", "Mali", "Mauritania", "Mauritius", "Mozambique", 
"Namibia", "Niger", "Nigeria", "Reunion", "Rwanda", "Sao Tome and Principe", 
"Senegal", "Seychelles", "Sierra Leone", "Somalia", "South Africa", 
"South Sudan", "Sudan", "Swaziland", "Tanzania", "Togo", "Uganda", 
"Zambia", "Zimbabwe"), class = "factor"), X1 = c(-0.18, -1.03, 
0.6, 1.55, 0.22, 0.26, 0.76, 2.15, -1.43, 0.99, 1.79, -0.39, 
1.73, 1.57, 1.11, -0.09, -1.49, -0.46, -0.48, -1.22, -0.78, -1.46, 
-1.22, 0.35, 0.45, 1.29, -1.37, -0.61, 0.92, -1.3, 0.42, -1.18, 
1.4, -0.83, 0.06, -0.76, -0.19, -0.37, -0.63, 0.64, 0.93, 0.33, 
-0.76, -0.21, -0.59, -0.41, -0.74, 0.39, -1.1, 1.35), X2 = c(-0.22, 
-0.42, 0.72, -0.59, -1.27, 0.64, -1.35, -1.4, -0.35, -1.43, 1.07, 
-0.01, -0.51, 0.11, 1.14, -0.89, 0.77, 1.45, -1.67, -0.83, 0.71, 
0.92, 1.63, 1.68, 0.23, -0.18, 0.07, 0.8, -0.02, 0.82, -0.72, 
-0.41, -0.26, 0.02, -1.68, 1.67, 0.18, 0.98, 1.45, 0.31, -1.23, 
-1.38, -0.63, 1.41, -0.12, 0, -1.3, -1.64, 0.21, 1.52)), .Names = c("Country", 
"X1", "X2"), row.names = c(NA, -50L), class = "data.frame") 

Antwort

5

„Im Idealfall würde Ich mag auf keinen Maßstab alle haben“: Dies wird durch Hinzufügen des Arguments showscale=F zu plot_ly() erreicht wird.

„Permanente Anzeige der Ländernamen“: Dies wird durch das Hinzufügen einer scattergeo Plot Schicht durchgeführt wird, wie mit einem kleinen Unterschied in this post, beschrieben. Da Ihre Datenrahmen eine Spalte von Ländernamen enthält, aber nicht eines der Ländercodes, müssen Sie das Argument hinzufügen locationmode = 'country names'

p <- plot_ly(df, z = member, type = 'choropleth', 
      locations = Country, locationmode = 'country names', 
      text = Country, hoverinfo = "text", 
      showscale=F, inherit =F) %>% 
    layout(geo = g, title = "Energy markets in Africa") %>% 
    add_trace(type="scattergeo", 
      locationmode = 'country names', locations = Country, 
      text = Country, mode="text", 
      textfont = list(color=rgb(1,0.5,0.3), size =12)) 

Sie müssen verschiedene Farbschemata ausprobieren, einen zu finden, die effektiv die Cluster zeigt, während die permanenten Bezeichnungen der Ländernamen dagegen sichtbar machen. Es gibt wahrscheinlich wenig, was Sie tun können, dass sich die permanenten Länderbezeichnungen überlappen, wenn die Karte herausgezoomt wird. Mit zusätzlichem Aufwand können Sie für jede der Beschriftungen eine lat-long-Position angeben, anstatt sich auf ihre Standardpositionen zu verlassen. Dies kann dazu beitragen, das Erscheinungsbild der Karte zu verbessern, indem die Beschriftungen besser getrennt werden. Ich nehme jedoch an, dass Sie, da Sie nach permanenten Labels gefragt haben, nur die Karte mit einem geeigneten Zoom verwenden wollen, wo sie in Ordnung erscheinen.

Um die Textfelder, die Sie beschreiben, hinzuzufügen, können Sie Annotationslayouts verwenden (eine Annotation pro Cluster). Ich zeige hier, wie man einen mit einem violetten Rand und einen zweiten mit einem Türkis hinzufügt. Sie müssen dies an das Farbschema anpassen, das Sie am Ende verwenden.

box1 <- list(
    x = 0.3, 
    y = 0.5, 
    yanchor = "top", 
    borderpad = 2, 
    bordercolor = rgb(0.5,0.1,0.5),  # set this same as color of cluster 1 
    borderwidth = 5, 
    text = paste("1. Cluster, ", 
       sum(df$member==1),  # number of countries in cluster 
       " Countries<br>X1 = ", # use <br> for line breaks 
       format(round(cluster.means[1,]$X1, 2), nsmall = 2), 
       "<br>X2 = ", 
       format(round(cluster.means[1,]$X2, 2), nsmall = 2)), 
    align = "left", 
    showarrow = F) 

box2 <- list(
    x = 0.3, 
    y = 0.4, 
    yanchor = "top", 
    borderpad = 2, 
    bordercolor = rgb(0.1,0.5,0.5), 
    borderwidth = 5, 
    text = paste("2. Cluster, ", 
       sum(df$member==2), 
       " Countries<br>X1 = ", 
       format(round(cluster.means[2,]$X1, 2), nsmall = 2), 
       "<br>X2 = ", 
       format(round(cluster.means[2,]$X2, 2), nsmall = 2)), 
    align = "left", 
    showarrow = F) 

p %>% layout(annotations = list(box1, box2)) 

enter image description here

+0

Wow! das ist großartig, danke :-) Ich habe eine Frage: Ich füge die anderen Kästchen hinzu und mache den "y-Wert" jeder Box um 0,1 weniger als oben. Am Ende füge ich sie alle zusammen wie diese Box = Liste (Box1, Box2, Box3, Box4, Box5) und ordne 'Box' den" Annotationen "zu. Aber leider ist der Abstand zwischen den Boxen nicht immer gleich ... warum? – Joni

+0

Der Standardanker für Anmerkungen ist "automatisch". Leider bedeutet das plotly, jede Box an der x, y-Position unterschiedlich zu verankern, je nachdem welcher Ankerpunkt der gegebenen y-Koordinate am nächsten kommt. Das Mittel ist einfach. Fügen Sie die Zeile 'yanchor =" top "' zu jeder der Anmerkungslisten hinzu. Ich habe die Antwort damit bearbeitet. – dww

+0

Außerdem wurde in der Anweisung paste() eine falsch platzierte Klammer bearbeitet (jetzt korrigiert) und die Textfelder um Textfelder erweitert, um die Darstellung zu verbessern. – dww

Verwandte Themen