Lad os antage, at jeg har tre datasæt:
X = [1,2,3,4]
Y1 = [4,8,12,16]
Y2 = [1,4,9,16]
Jeg kan lave et spredningsdiagram over dette:
from matplotlib import pyplot as plt
plt.scatter(X,Y1,color='red')
plt.scatter(X,Y2,color='blue')
plt.show()
Hvordan kan jeg gøre dette med 10 sæt?
Jeg søgte efter dette og kunne ikke finde nogen reference til det jeg spørger om.
Edit: præcisering (forhåbentlig) af mit spørgsmål
Hvis jeg kalder scatter flere gange, kan jeg kun indstille den samme farve på hver scatter. Jeg ved også, at jeg kan indstille et farve array manuelt, men jeg er sikker på, at der er en bedre måde at gøre dette på. Mit spørgsmål er så: "Hvordan kan jeg automatisk scatter-plotte mine flere datasæt, hver med en anden farve.
Hvis det hjælper, kan jeg nemt tildele et unikt nummer til hvert datasæt.
Jeg ved ikke, hvad du mener med 'manuelt'. Du kan nemt nok vælge et farvekort og lave et farveskema:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]
colors = cm.rainbow(np.linspace(0, 1, len(ys)))
for y, c in zip(ys, colors):
plt.scatter(x, y, color=c)
[]]1
Eller du kan lave din egen farvecyklist ved hjælp af itertools.cycle
og angive de farver, du vil sløjfe over, og bruge next
til at få den ønskede farve. For eksempel, med 3 farver:
import itertools
colors = itertools.cycle(["r", "b", "g"])
for y in ys:
plt.scatter(x, y, color=next(colors))
[]]2
Når jeg tænker over det, er det måske også renere ikke at bruge zip
med den første:
colors = iter(cm.rainbow(np.linspace(0, 1, len(ys))))
for y in ys:
plt.scatter(x, y, color=next(colors))
Den normale måde at plotte plotter med punkter i forskellige farver i matplotlib er ved at sende en liste over farver som en parameter.
F.eks:
import matplotlib.pyplot
matplotlib.pyplot.scatter([1,2,3],[4,5,6],color=['red','green','blue'])
[]]1
Når du har en liste af lister, og du vil have dem farvelagt pr. liste. Jeg tror, at den mest elegante måde er den foreslået af @DSM, bare lave en løkke, der laver flere kald til scatter.
Men hvis du af en eller anden grund ønskede at gøre det med kun ét opkald, kan du lave en stor liste af farver, med en listeforståelse og lidt gulvdeling:
import matplotlib
import numpy as np
X = [1,2,3,4]
Ys = np.array([[4,8,12,16],
[1,4,9,16],
[17, 10, 13, 18],
[9, 10, 18, 11],
[4, 15, 17, 6],
[7, 10, 8, 7],
[9, 0, 10, 11],
[14, 1, 15, 5],
[8, 15, 9, 14],
[20, 7, 1, 5]])
nCols = len(X)
nRows = Ys.shape[0]
colors = matplotlib.cm.rainbow(np.linspace(0, 1, len(Ys)))
cs = [colors[i//len(X)] for i in range(len(Ys)*len(X))] #could be done with numpy's repmat
Xs=X*nRows #use list multiplication for repetition
matplotlib.pyplot.scatter(Xs,Ys.flatten(),color=cs)
[]]2
cs = [array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
...
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00])]
Dette spørgsmål er lidt vanskeligt før januar 2013 og matplotlib 1.3.1 (august 2013), som er den ældste stabile version, du kan finde på matplotlib-webstedet. Men efter det er det ret trivielt.
Fordi den nuværende version af matplotlib.pylab.scatter
understøtter tildeling af: array af farvenavnstrang, array af float-tal med farvekort, array af RGB eller RGBA.
dette svar er dedikeret til @Oxinabox's uendelige passion for at rette 2013-versionen af mig selv i 2015.
du har to muligheder for at bruge scatter-kommandoen med flere farver i et enkelt opkald.
som pylab.scatter
kommando støtte bruge RGBA array til at gøre hvilken farve du ønsker;
tilbage i begyndelsen af 2013 var der ingen mulighed for at gøre det, da kommandoen kun understøtter en enkelt farve for hele scatterpunktsamlingen. Da jeg lavede mit 10000-line projekt, fandt jeg ud af en generel løsning til at omgå det. så det er meget klædeligt, men jeg kan gøre det i hvilken som helst form, farve, størrelse og gennemsigtig. dette trick kan også anvendes til at tegne sti samling, linje samling....
koden er også inspireret af kildekoden til pyplot.scatter
, jeg har bare duplikeret hvad scatter gør uden at udløse det til at tegne.
kommandoen pyplot.scatter
returnerer et PatchCollection
Objekt, i filen "matplotlib/collections.py" en privat variabel _facecolors
i Collection
klassen og en metode set_facecolors
.
så når du har et scatterpoint at tegne, kan du gøre dette:
# rgbaArr is a N*4 array of float numbers you know what I mean
# X is a N*2 array of coordinates
# axx is the axes object that current draw, you get it from
# axx = fig.gca()
# also import these, to recreate the within env of scatter command
import matplotlib.markers as mmarkers
import matplotlib.transforms as mtransforms
from matplotlib.collections import PatchCollection
import matplotlib.markers as mmarkers
import matplotlib.patches as mpatches
# define this function
# m is a string of scatter marker, it could be 'o', 's' etc..
# s is the size of the point, use 1.0
# dpi, get it from axx.figure.dpi
def addPatch_point(m, s, dpi):
marker_obj = mmarkers.MarkerStyle(m)
path = marker_obj.get_path()
trans = mtransforms.Affine2D().scale(np.sqrt(s*5)*dpi/72.0)
ptch = mpatches.PathPatch(path, fill = True, transform = trans)
return ptch
patches = []
# markerArr is an array of maker string, ['o', 's'. 'o'...]
# sizeArr is an array of size float, [1.0, 1.0. 0.5...]
for m, s in zip(markerArr, sizeArr):
patches.append(addPatch_point(m, s, axx.figure.dpi))
pclt = PatchCollection(
patches,
offsets = zip(X[:,0], X[:,1]),
transOffset = axx.transData)
pclt.set_transform(mtransforms.IdentityTransform())
pclt.set_edgecolors('none') # it's up to you
pclt._facecolors = rgbaArr
# in the end, when you decide to draw
axx.add_collection(pclt)
# and call axx's parent to draw_idle()