Matplotlib-일련의 선 플롯에 컬러 바 추가
변수 z의 여러 다른 값에 대해 두 변수 (x, y)에 대한 일련의 선 플롯이 있습니다. 일반적으로 다음과 같은 범례가있는 선 플롯을 추가합니다.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
# suppose mydata is a list of tuples containing (xs, ys, z)
# where xs and ys are lists of x's and y's and z is a number.
legns = []
for(xs,ys,z) in mydata:
pl = ax.plot(xs,ys,color = (z,0,0))
legns.append("z = %f"%(z))
ax.legends(legns)
plt.show()
하지만 그래프가 너무 많고 범례가 그래프를 덮을 것입니다. 차라리 색상에 해당하는 z 값을 나타내는 컬러 바가 있습니다. 나는 갤러리에서 그런 것을 찾을 수 없으며 컬러 바를 다루는 모든 시도가 실패했습니다. 분명히 컬러 바를 추가하기 전에 플롯 모음을 만들어야합니다.
이 작업을 수행하는 쉬운 방법이 있습니까? 감사.
편집 (설명) :
나는 다음과 같이하고 싶었습니다.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
fig = plt.figure()
ax = fig.add_subplot(111)
mycmap = cm.hot
# suppose mydata is a list of tuples containing (xs, ys, z)
# where xs and ys are lists of x's and y's and z is a number between 0 and 1
plots = []
for(xs,ys,z) in mydata:
pl = ax.plot(xs,ys,color = mycmap(z))
plots.append(pl)
fig.colorbar(plots)
plt.show()
그러나 이것은 Matplotlib 참조에 따르면 작동하지 않을 것입니다. 플롯 목록은 이것이 무엇을 의미하든 "맵핑 가능"이 아니기 때문입니다.
다음을 사용하여 대체 플롯 함수를 만들었습니다 LineCollection
.
def myplot(ax,xs,ys,zs, cmap):
plot = lc([zip(x,y) for (x,y) in zip(xs,ys)], cmap = cmap)
plot.set_array(array(zs))
x0,x1 = amin(xs),amax(xs)
y0,y1 = amin(ys),amax(ys)
ax.add_collection(plot)
ax.set_xlim(x0,x1)
ax.set_ylim(y0,y1)
return plot
xs
그리고 ys
x 및 y 좌표의리스트의 나열하고 zs
각 라인 색상 화하는 다른 조건의 목록. 그래도 약간 엉망진창 같네요 ... 좀 더 깔끔한 방법이있을 거라 생각 했어요. plt.plot()
기능 의 유연성이 마음에 듭니다 .
(나는 이것이 오래된 질문이라는 것을 알고 있지만 ...) 컬러 바는 matplotlib.cm.ScalarMappable
, plt.plot
스칼라 매핑 가능하지 않은 라인을 생성 하므로 컬러 바를 만들려면 스칼라 매핑 가능하게 만들어야합니다.
확인. 따라서 a의 생성자 ScalarMappable
는 a cmap
와 norm
인스턴스를 사용합니다. (norms는 데이터를 0-1 범위로 확장하고, 이미 작업 한 cmaps는 0-1 사이의 숫자를 취하고 색상을 반환합니다.) 따라서 귀하의 경우 :
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))
plt.colorbar(sm)
데이터가 이미 0-1 범위에 있으므로 sm
생성을 다음과 같이 단순화 할 수 있습니다 .
sm = plt.cm.ScalarMappable(cmap=my_cmap)
누군가에게 도움이되기를 바랍니다.
편집 : matplotlib v1.2 이상의 경우 코드는 다음과 같습니다.
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
편집 : matplotlib v1.3 이상의 경우 코드는 다음과 같습니다.
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
편집 : matplotlib v3.1 이상의 경우 다음을 단순화합니다.
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
plt.colorbar(sm)
다음은 plt.plot ()을 사용하는 동안이를 수행하는 한 가지 방법입니다. 기본적으로 일회용 플롯을 만들고 거기에서 컬러 바를 가져옵니다.
import matplotlib as mpl
import matplotlib.pyplot as plt
min, max = (-40, 30)
step = 10
# Setting up a colormap that's a simple transtion
mymap = mpl.colors.LinearSegmentedColormap.from_list('mycolors',['blue','red'])
# Using contourf to provide my colorbar info, then clearing the figure
Z = [[0,0],[0,0]]
levels = range(min,max+step,step)
CS3 = plt.contourf(Z, levels, cmap=mymap)
plt.clf()
# Plotting what I actually want
X=[[1,2],[1,2],[1,2],[1,2]]
Y=[[1,2],[1,3],[1,4],[1,5]]
Z=[-40,-20,0,30]
for x,y,z in zip(X,Y,Z):
# setting rgb color based on z normalized to my range
r = (float(z)-min)/(max-min)
g = 0
b = 1-r
plt.plot(x,y,color=(r,g,b))
plt.colorbar(CS3) # using the colorbar info I got from contourf
plt.show()
조금 낭비이지만 편리합니다. 정보를 다시 생성하지 않고 plt.colorbar ()를 호출 할 수 있으므로 여러 플롯을 만드는 경우에도별로 낭비가 아닙니다.
다음은 Boris 와 Hooked가 제공 한 상위 답변에서 영감을 얻은 약간 단순화 된 예제입니다 (좋은 아이디어에 감사드립니다!).
1. 개별 컬러 바
에서 생성 된 컬러 맵 mpl.cm.get_cmap()
은 colorbar()
인수 로 필요한 매핑 가능한 이미지가 아니기 때문에 이산 컬러 바가 더 복잡 합니다. dummie mappable은 아래와 같이 생성되어야합니다.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
cmap = mpl.cm.get_cmap('jet', n_lines)
fig, ax = plt.subplots(dpi=100)
# Make dummie mappable
dummie_cax = ax.scatter(c, c, c=c, cmap=cmap)
# Clear axis
ax.cla()
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
fig.colorbar(dummie_cax, ticks=c)
plt.show();
2. 연속 컬러 바
연속 컬러 바는 덜 관여하므로에 mpl.cm.ScalarMappable()
대한 "이미지"를 얻을 수 있습니다 colorbar()
.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.jet)
cmap.set_array([])
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show();
[Side note] 이 예에서는 개인적으로 왜 cmap.set_array([])
필요한지 모르겠습니다 (그렇지 않으면 오류 메시지가 표시됨). 누군가가 후드 아래의 원칙을 이해한다면 의견을 말하십시오 :)
여기에 다른 답변은 실제로 좋은 스타일이 아닌 더미 플롯을 사용하려고 시도하므로 여기에 대한 일반 코드가 있습니다.
개별 컬러 바
별개의 컬러 바는 다른 정규화를 사용하여 연속 컬러 바가 생성되는 것과 동일한 방식으로 생성됩니다. 이 경우 a를 BoundaryNorm
사용해야합니다.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)
cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([]) # this line may be ommitted for matplotlib >= 3.1
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()
참조 URL : https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots
'Programing' 카테고리의 다른 글
iOS 앱의 첫 실행 감지 (0) | 2020.12.28 |
---|---|
WPF WebBrowser 컨트롤-스크립트 오류를 억제하는 방법? (0) | 2020.12.28 |
Array가 제네릭 유형이 아닌 이유는 무엇입니까? (0) | 2020.12.27 |
디버깅하는 동안 표현식을 평가하는 Xcode (0) | 2020.12.27 |
Objective-C : NSURL에 쿼리 매개 변수를 추가하는 방법은 무엇입니까? (0) | 2020.12.27 |