#------------------------------------# # # # Week13: Einiges zu Farben # # und Farbpaletten in R # # # #------------------------------------# # Wir plotten die Dichte der Standardnormalverteilung: x = seq(from = -5, to = 5, by = 0.01 ) plot(x, dnorm(x,mean=0,sd=1) ) # Wir plotten die Dichte, jetzt in rot: plot(x, dnorm(x,mean=0,sd=1), col="red" ) # offensichtlich tut der Textstring mycol = "red" # eine Farbe codieren. mycol class(mycol) str(mycol) mode(mycol) # ..ist ein normaler Textstring # Es gibt eine Funktion col2rgb(), schauen wir uns an, # was die macht: col2rgb("red") # ok, sieht Farb-maessig aus.. col2rgb(mycol) # dasselbe Resultat col2rgb("green") col2rgb("blue") col2rgb("yellow") col2rgb("magenta") col2rgb("cyan") col2rgb("pink") # etwas komplizierter.. col2rgb("black") col2rgb("white") col2rgb("detlef") # error: invalid color name # es scheint also vordefinierte Farbnamen zu geben, # man kann sie sich mit der colors()-Funktion # anzeigen lassen: farben = colors() farben # das sind 657 Stueck. Nehmen wir etwa Nummer 634, # "tomato4": plot(x, dnorm(x,mean=0,sd=1), col="tomato4" ) # funktioniert plot(x, dnorm(x,mean=0,sd=1), col="tomato5" ) # error: invalid color name col2rgb("tomato4") # geht col2rgb("tomato5") # error # Schauen wir uns die vordefinierten Farben # mal an: # irgendwas zum Plotten: x = rnorm(5000) y = rnorm(5000) # alle vordefinierten Farben: farben = colors() # 10 x 10 plot array: # In dem par()-Befehl gleich unten steht mar fuer margin, aus der ?par()-Hilfe: # mar: A numerical vector of the form c(bottom, left, top, right) which gives # the number of lines of margin to be specified on the four sides of the plot. # The default is c(5, 4, 4, 2) + 0.1. par(mfrow=c(10,10), mar=c(1,0,2,0)+0.1, col.axis="white") # keine Beschriftung der Axen, ist nur im Weg.. i=0 #count colors for(farbe in farben) { i=i+1 info = paste(farbe,", ",i,sep="") plot(x, y, col=farbe, main=info ) if(i%%100==0) { readline("press enter for next 100 colors") } }#next 100 colors #---------------------------# # Farbpaletten # #---------------------------# # Recht haeufig hat man die folgende Situation: # Man hat n verschiedene Dinge, etwa n Kurven # oder n Datasets, die man in einem Plotfenster # plotten moechte, und die n Sachen sollen dann # n verschiedene Farben bekommen. # Oder: man hat eine Funktion in der (x,y)-Ebene, # man moechte im wesentlichen die Hoehenlinien # plotten, aber das farblich anzeigen, kleine # Werte sind blau oder schwarz und grosse Werte # sind rot oder weiss. # Das geht mit Farbpaletten. Es gibt vordefinierte # Farbpaletten oder man kann sie sich auch selber # zusammenstellen: # Wir geben uns n Standardabweichungen sigma vor, # sagen wir, zwischen 1/2 und 2, n = 20 sigma = seq(from = 1/2, to = 2, length=n) # und wollen dann die n Dichten fuer die Normalverteilung # fuer diese sigma's in einem Diagramm plotten, wir nehmen # jetzt das Intervall [-10,10]: x = seq(from = -10, to=10, by=0.01) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]) ) } # Das sieht nicht so schoen aus, wir wollen jeder Dichte # eine eigene Farbe geben. Wir benutzen die rainbow()- # Farbpalette: n = 20 sigma = seq(from = 1/2, to = 2, length=n) mycols = rainbow(n) x = seq(from = -10, to=10, by=0.01) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycols[i] ) # hier benutzen wir also die Farbpalette rainbow(20) } # Das sieht huebsch aus!! # Jetzt dasselbe mit n=100 Kurven: n = 100 mycols = rainbow(n) sigma = seq(from = 1/2, to = 2, length=n) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycols[i] ) # hier benutzen wir also die Farbpalette rainbow(100) } # Es gibt 5 vordefinierte Farbpaletten, wovon die rainbow()-Palette aber # am nutzlichsten erscheint: #mycols = rainbow(n) #mycols = heat.colors(n) #mycols = terrain.colors(n) #mycols = cm.colors(n) mycols = topo.colors(n) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycols[i] ) } # Schauen wir uns an, wie eine Farbpalette technich aussieht: rainbow(5) # 5 Farben in Hexadezimal-Code rainbow(20) rainbow(100) # 100 Farben in Hexadezimal-Code # die Hexadezimal-Ziffern sind # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, und # A = 10 # B = 11 # C = 12 # D = 13 # E = 14 # F = 15 # man hat also etwa # FF = 15 * 16^1 + 15 * 16^0 = 255 # 4D = 4 * 16^1 + 13 * 16^0 = 77 # Mit der rgb()-Funktion (vorhin hatten wir col2rgb(), das war was anderes) # kann man sich den Hexadezimal-Code einer Farbe anzeigen lassen: ?rgb() # man kann die ueblichen 0...255 als Input nehmen -> maxColorValue = 255 # oder auch reelle Zahlen zwischen 0 und 1, das ist die Default-Einstellung # und das entspricht maxColorValue = 1 col2rgb("red") # -> 255, 0, 0 rgb(255,0,0) # liefert error: color intensity not in [0,1] rgb(255,0,0,maxColorValue=255) # das geht: "#FF0000" col2rgb("yellow") # -> 255, 255, 0 rgb(255,255,0,maxColorValue=255) # das geht: "#FFFF00" # wie ueblich nehmen R-Funktionen gerne Vektoren als Input: rgb(255, 0:255, 0, maxColorValue=255 ) # das sind 256 Farben in Hex-Code # Zurueck zu den Farbpaletten: Betrachten wir # noch einmal dieses Bild: n = 100 mycols = rainbow(n) sigma = seq(from = 1/2, to = 2, length=n) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycols[i] ) } # recht haeufig moechte man, dass das nicht von rot bis rot geht, sondern etwa # von weiss ueber rot ueber gruen ueber blau zu schwarz, # dazu kann man sich eigene Farbpaletten definieren: es gibt diverse packages, # aber sehr einfach geht das mit der sehr nuetzlichen colorRamp()-Funktion, die # in der Standard-Version von R enthalten ist: ?colorRamp() # probieren wir das mal aus: ramp1 = colorRamp( c("red","white") ) # einfache, intuitive Syntax!! ramp1 # das ist eine Funktion, das sind noch keine Farben.. mycol = ramp1(100) mycol # ok, so einfach geht das nicht, dieses # ramp1 produziert wohl was rgb-maessiges.. ramp1( seq(0,1,length = 100) ) # ok, das sind jetzt 100 Farben in rgb-Code, # die zwischen rot und weiss interpolieren # Also der Input fuer ramp1 muessen dann offensichtlich # Zahlen zwischen 0 und 1 sein. rgb( ramp1(seq(0,1,length = 100)) , max=255 ) # das sind jetzt 100 Farben in hex-code mycol1 = rgb( ramp1(seq(0,1,length = 100)) , max=255 ) mycol1 # quick check: n = 100 plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycol1[i] ) } # soweit ok.. # jetzt noch eine Farbpalette von blau nach schwarz: ramp2 = colorRamp(c("blue","black")) # super intuitive Syntax!! ramp2 # das ist eine Funktion mycol2 = rgb( ramp2(seq(0,1,length = 100) ), max = 255) mycol2 # 100 Farben in Hex-Code von blau="#0000FF" nach schwarz="#000000" # quick check: n = 100 plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycol2[i] ) } # soweit ok.. # jetzt nehmen wir noch die rainbow()-Palette, lassen die bei rot starten, start=0, # und lassen die aber nur bis blau laufen, end=4/6, mit 500 Farben: mycol0 = rainbow(500, start=0, end=4/6 ) mycol0 # quick check: n = 500 sigma = seq(from = 1/2, to = 2, length=n) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycol0[i] ) } # soweit ok.. # Jetzt packen wir alles zusammen: mycol = c( rev(mycol1) , mycol0 , mycol2 ) # von weiss nach rot nach blau nach schwarz.. length(mycol) # 700 Farben # let's check: n = 700 sigma = seq(from = 1/2, to = 2, length=n) plot(x , dnorm(x,mean=0,sd=sigma[1]) ) for(i in 2:n) { points(x, dnorm(x,mean=0,sd=sigma[i]), col = mycol[i] ) } # ..passt alles! #---------------------------------------# # Und noch ein Beispiel fuer einen # # farbigen Contour-Plot: # #---------------------------------------# M = 100 N = 200 lattice = t(outer(1:N,1i*(1:M),FUN="+")) # set up lattice as complex numbers donors = sample(lattice,N*M/100,replace=FALSE) # 1% random sites are donor atoms # picture: par(pin=c(6,6*M/N)) # Plot-Verhaeltnis N zu M, genauer: plot(donors) # absolute Groesse 6 x 6M/N inch RandPot = matrix(0,nrow=M,ncol=N) for(donor in donors) { distances = sqrt(abs(lattice-donor)^2 + 15) RandPot = RandPot + 1/distances^3 } # picture: par(pin=c(6,6*M/N)) contour(1:N, 1:M, t(RandPot), main="Random Potential" ) # mit Default-Farben: image(1:N, 1:M, t(RandPot), main="Random Potential") # mit eigener Farbpalette: image(1:N, 1:M, t(RandPot), main="Random Potential", col=rev(mycol) ) # oder mit Legende, wir brauchen ein package: require(fields) image.plot(1:N, 1:M, t(RandPot), main="Random Potential", col=rev(mycol) )