Mam dane o temperaturze z wielu urządzeń na różnych płytkach, na przykład na płycie 1 mam temperaturę dla samej PCB i 3 różnych FET i podobnie dla płyt 2 i 3. Wczytuję dane do ramki danych i chcę wykreślić dane razem z tym samym kolorem dla każdej testowanej płytki, ale z różnymi znacznikami dla każdego urządzenia na płytkach. Na przykład wszystkie pomiary z płytki 1 byłyby niebieskie, z temperaturą PCB za pomocą znacznika „+”, FET1 za pomocą znacznika „v” itp.
Czytałem pliki w ten sposób:

for file_name in glob.glob(path+'*.csv'):
    filename[i] = os.path.basename(file_name)
    print(filename[i])
    #x[i]= np.genfromtxt(path+ filename[i], delimiter=',',skip_header=20,usecols=(2,4,6,8))
    x[i]=pd.read_csv(path+filename[i], header=0,usecols=[2,4,6,8], skiprows=12,names=['PCB', 'FET1', 'FET2', 'FET3'])

I utwórz tablicę ramek danych.

Następnie wykreślam różne kolumny:

colors=['r','b','g','c','m']
for i in range(len(filename)):
    #plt.figure()
    plt.plot(sc.decimate(x[i]['PCB'],5),'-+'+colors[i],label="PCB")
    plt.plot(sc.decimate(x[i]['FET1'],5),'-v'+colors[i],label='FET1')
    plt.plot(sc.decimate(x[i]['FET2'],5),'-x'+colors[i],label='FET2')
    plt.plot(sc.decimate(x[i]['FET3'],5),'-o'+colors[i],label='FET3')
    leg=np.append(leg, filename[i][0:7])
    #plt.show()


plt.show()
plt.legend(leg)

enter image description here

Znaczniki są poprawnie wyświetlane, ale podczas iteracji w ramkach danych informacje o kolorze zostały utracone. W jaki sposób mogę wykreślić dane i ułożyć je tak, aby legenda używała tego samego koloru dla każdej grupy wierszy (zgodnie z indeksem i)?

Oto kilka przykładowych danych: plik 1:

Name:,Data Instr INSTR 3/5/2020 11:51:59,,,,,,,,,,,,
Owner:,lab1,,,,,,,,,,,,
Comments:,,,,,,,,,,,,,
Acquisition Date:,3/5/2020 11:51,,,,,,,,,,,,
&Instrument:,34970A,Address:,ASRL11::INSTR,Modules:,1,Slot3:,34901A,,,,,,
Total Channels:,4,,,,,,,,,,,,
Channel,Name,Function,Range,Resolution,AdvSettings,Scale,Gain,Offset,Label,Test,Low,High,HWAlarm
316,PCB_CTR,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
317,Q24,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
318,Q25,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
319,Q18,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
Scan  Control:,Start Action:,Immediately,Stop Action:,User Terminated,,,,,,,,,
Scan,Time,316 <PCB_CTR> (C),Alarm 316,317 <Q24> (C),Alarm 317,318 <Q25> (C),Alarm 318,319 <Q18> (C),Alarm 319,,,,
1,3/5/2020 11:51:59:168,30.471,0,29.241,0,29.165,0,33.302,0,,,,
2,3/5/2020 11:52:01:152,32.197,0,30.634,0,30.564,0,34.819,0,,,,
3,3/5/2020 11:52:03:152,33.795,0,32.019,0,31.879,0,36.848,0,,,,
4,3/5/2020 11:52:05:152,35.315,0,33.383,0,33.236,0,38.282,0,,,,
5,3/5/2020 11:52:07:152,36.965,0,34.734,0,34.62,0,39.946,0,,,,
6,3/5/2020 11:52:09:152,38.255,0,36.054,0,35.776,0,41.18,0,,,,
7,3/5/2020 11:52:11:152,39.467,0,37.328,0,37.028,0,42.258,0,,,,

Plik 2

Name:,Data Instr INSTR 3/5/2020 10:03:21,,,,,,,,,,,,
Owner:,lab1,,,,,,,,,,,,
Comments:,,,,,,,,,,,,,
Acquisition Date:,3/5/2020 10:03,,,,,,,,,,,,
&Instrument:,34970A,Address:,ASRL11::INSTR,Modules:,1,Slot3:,34901A,,,,,,
Total Channels:,4,,,,,,,,,,,,
Channel,Name,Function,Range,Resolution,AdvSettings,Scale,Gain,Offset,Label,Test,Low,High,HWAlarm
316,PCB_CTR,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
317,Q24,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
318,Q25,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
319,Q18,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
Scan  Control:,Start Action:,Immediately,Stop Action:,User Terminated,,,,,,,,,
Scan,Time,316 <PCB_CTR> (C),Alarm 316,317 <Q24> (C),Alarm 317,318 <Q25> (C),Alarm 318,319 <Q18> (C),Alarm 319,,,,
1,3/5/2020 10:03:21:164,46.334,0,43.755,0,45.706,0,49.129,0,,,,
2,3/5/2020 10:03:22:149,46.997,0,44.262,0,46.35,0,49.773,0,,,,
3,3/5/2020 10:03:23:149,47.615,0,44.671,0,46.974,0,50.402,0,,,,
4,3/5/2020 10:03:24:149,48.267,0,45.229,0,47.628,0,50.879,0,,,,
5,3/5/2020 10:03:25:149,48.861,0,45.711,0,48.164,0,51.495,0,,,,
6,3/5/2020 10:03:26:149,49.455,0,46.323,0,48.783,0,51.9,0,,,,
7,3/5/2020 10:03:27:149,50.014,0,46.796,0,49.351,0,52.334,0,,,,

Plik 3

Name:,Data Instr INSTR 3/5/2020 13:41:06,,,,,,,,,,,,
Owner:,lab1,,,,,,,,,,,,
Comments:,,,,,,,,,,,,,
Acquisition Date:,3/5/2020 13:41,,,,,,,,,,,,
&Instrument:,34970A,Address:,ASRL11::INSTR,Modules:,1,Slot3:,34901A,,,,,,
Total Channels:,4,,,,,,,,,,,,
Channel,Name,Function,Range,Resolution,AdvSettings,Scale,Gain,Offset,Label,Test,Low,High,HWAlarm
316,PCB_CTR,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
317,Q24,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
318,Q25,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
319,Q18,Temp (Type K),None,C,Temp (Type K)#1#0.016#Auto#0.001#C#Internal#0#false,FALSE,1,0,C,High Only,0,105,Alarm 1
Scan  Control:,Start Action:,Immediately,Stop Action:,User Terminated,,,,,,,,,
Scan,Time,316 <PCB_CTR> (C),Alarm 316,317 <Q24> (C),Alarm 317,318 <Q25> (C),Alarm 318,319 <Q18> (C),Alarm 319,,,,
1,3/5/2020 13:41:06:162,28.121,0,26.882,0,28.785,0,31.061,0,,,,
2,3/5/2020 13:41:08:147,30.582,0,27.873,0,30.691,0,33.024,0,,,,
3,3/5/2020 13:41:10:147,31.782,0,28.935,0,32.578,0,34.876,0,,,,
4,3/5/2020 13:41:12:147,34.003,0,30.094,0,34.247,0,36.652,0,,,,
5,3/5/2020 13:41:14:147,35.097,0,31.199,0,35.975,0,38.142,0,,,,
6,3/5/2020 13:41:16:147,36.708,0,32.334,0,37.504,0,39.721,0,,,,
7,3/5/2020 13:41:18:147,38.274,0,33.508,0,39.048,0,41.198,0,,,,

Dziękuję za pomoc.

EDYTUJ

Z pomocą wkładu @ ilke444 zbliżyłem się do tego, czego chcę, ale nadal mam problemy:

for i in range(len(filename)):
    l=plt.plot(sc.decimate(x[i]['PCB'],5),'-+'+colors[i],label="PCB")
    lines=np.append(lines,l[0].get_label())
    l=plt.plot(sc.decimate(x[i]['FET1'],5),'-v'+colors[i],label='FET1')
    lines=np.append(lines,l[0].get_label())
    l=plt.plot(sc.decimate(x[i]['FET2'],5),'-x'+colors[i],label='FET2')
    lines=np.append(lines,l[0].get_label())
    l=plt.plot(sc.decimate(x[i]['FET3'],5),'-o'+colors[i],label='FET3')
    lines=np.append(lines,l[0].get_label())

    linesclr=np.append(linesclr, l)  # save color info
    names = np.append(names, filename[i][0:7])

fig.legend(lines, loc=1)
fig.legend(linesclr, labels=names, loc=2)
plt.show()

Jak widać poniżej, druga legenda, którą próbuję dodać, nie pokazuje właściwych kolorów, tj. 1 kolor na odczytany plik (lewy górny róg):

enter image description here

Nie rozumiem, dlaczego legenda po lewej nie pokazuje właściwych kolorów, ponieważ informacje o kolorze znajdują się w każdym elemencie tablicy lineslr:

linesclr[0].get_color()
Out[4]: 'r'
linesclr[0].get_color()
Out[5]: 'r'
linesclr[1].get_color()
Out[6]: 'b'
linesclr[2].get_color()
Out[7]: 'g'

Co więcej, nie rozumiem, dlaczego znacznik nie zawsze jest okręgiem („o”) dla wszystkich kluczy w tej legendzie.

Rozwiązanie, którego szukam:

Wydaje mi się, że najlepszym sposobem przekazania informacji o działkach są 2 legendy, ale legenda po prawej stronie pokazuje tylko znaczniki dla każdej linii dla każdego typu urządzenia (czarna linia z odpowiednim znacznikiem) i legendę po lewej stronie pokazujące nazwy plików i kolory (linia bez znaczników) użyte do wszystkich odczytów temperatur z tego pliku.

Więc chciałbym, aby legenda po prawej stronie pokazała tylko 4 lokalizacje termopar z ich znacznikami:

+ PCB
v FET1 
x FET2 
o FET3

I legenda po lewej, aby pokazać: ACI50 # 5 na czerwono, ACI50 # na niebiesko, ACI50 # 6 na zielono, KDE5515 na niebiesko (lub dowolną liczbę plików wczytanych, każdy z odpowiednim kolorem wydruku).

Próbowałem czytać i pisać literaturę na temat matplotlib na temat legend i tworzenia własnych legend i szukałem przykładów w Internecie, ale nie mam większego sukcesu w zrozumieniu tego, co czytam!

0
jrive 9 marzec 2020, 20:50

2 odpowiedzi

Najlepsza odpowiedź

Mam nadzieję, że właśnie tego szukasz :)

Myślę, że możliwe są 2 rozwiązania:

Z góry przepraszam, że musiałem symulować dane, więc wykres nie wygląda jak uporządkowane linie, ale myślę, że i tak nie stanowi to problemu

  1. Z jedną legendą dla wszystkich plików:
import glob
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import scipy.signal as sc
import numpy as np

dfs = [] # store df
cmap = cm.get_cmap('Set1')
cols = {}

for i, fn in enumerate(glob.glob("*.csv")) :
    #dfs.append(pd.read_csv(fn, header=0, usecols=[2,4,6,8], skiprows=12, names=['PCB', 'FET1', 'FET2', 'FET3'])) # Uncommenting this line to read from your files should work
    dfs.append(pd.DataFrame(np.random.randn(100, 4), columns=['PCB', 'FET1', 'FET2', 'FET3'])) # Just random data
    cols[i] = cmap(i) # Maps one color to one file with a dict

mrks = {"PCB":'+',"FET1":'v',"FET2":'x',"FET3":'o'} # Maps one sensor to one marker type

fig, ax = plt.subplots(figsize=(12,12))
for n, d in enumerate(dfs) :
    ax.plot(sc.decimate(d['PCB'],5), ls='-', marker=mrks['PCB'], color=cols[n], label="PCB") # Use label to map to files
    ax.plot(sc.decimate(d['FET1'],5), ls='-', marker=mrks['FET1'], color=cols[n], label="FET1")
    ax.plot(sc.decimate(d['FET2'],5), ls='-', marker=mrks['FET2'], color=cols[n], label="FET2")
    ax.plot(sc.decimate(d['FET3'],5), ls='-', marker=mrks['FET3'], color=cols[n], label="FET3")

ax.legend()
plt.show()

Daje ten wykres:

One legend for whole data

  1. Z oddzielnymi legendami (przepraszam w moim przykładzie zamieniłem lokalizacje, ale możesz to łatwo dostosować
import glob
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import scipy.signal as sc
import numpy as np
from matplotlib.lines import Line2D

# create a marker for each thermocouple
mrks = {"PCB":'+',"FET1":'v',"FET2":'x',"FET3":'o'}
marker_legend = [Line2D([0], [0], lw=1, color="k", marker=v, label=k) for k, v in mrks.items()]
color_legend = []

dfs = [] # store df
cmap = cm.get_cmap('Set1')
cols = {}
for i, fn in enumerate(glob.glob("*.csv")) : # read files and map colors to each
    #dfs.append(pd.read_csv(fn, header=0, usecols=[2,4,6,8], skiprows=12, names=['PCB', 'FET1', 'FET2', 'FET3']))
    dfs.append(pd.DataFrame(np.random.randn(100, 4), columns=['PCB', 'FET1', 'FET2', 'FET3']))
    cols[i] = cmap(i)
    color_legend.append(Line2D([0], [0], color=cmap(i), lw=1, label=fn))

fig, ax = plt.subplots(figsize=(12,12))
for n, d in enumerate(dfs) :
    ax.plot(sc.decimate(d['PCB'],5), ls='-', marker=mrks['PCB'], color=cols[n])
    ax.plot(sc.decimate(d['FET1'],5), ls='-', marker=mrks['FET1'], color=cols[n])
    ax.plot(sc.decimate(d['FET2'],5), ls='-', marker=mrks['FET2'], color=cols[n])
    ax.plot(sc.decimate(d['FET3'],5), ls='-', marker=mrks['FET3'], color=cols[n])

first_legend = plt.legend(handles=marker_legend, loc="upper left")
ax = plt.gca().add_artist(first_legend)
second_legend = plt.legend(handles=color_legend, loc="upper right")

plt.show()

Oto wynikowa fabuła:

Separated legends

Jeśli nie chcesz używać cmap z matplotlib, nadal możesz utworzyć listę kolorów, o których wiesz, że będą dłuższe niż liczba plików, które przeczytasz i narysujesz z niej zamiast czegoś takiego:

cmap = ["r","g","b","cyan", ...]
...
for i, fn in enumerate(glob.glob("*.csv")) :
   ...
   cols[i] = cmap[i]
   ...
1
AnHo 16 marzec 2020, 08:50

Każdy wykres narysowany przez to samo wywołanie w pętli przepisuje legendę, mimo że dane są inne. Dlatego musisz je zapisać, a następnie dodać do legendy, gdy nadpisywanie nie jest już możliwe.

fig = plt.figure()
lines = []
colors=['r','b','g','c','m']
for i in range(len(filename)):
    l=plt.plot(sc.decimate(x[i]['PCB'],5),'-+'+colors[i],label="PCB")
    lines=np.append(lines,l)
    l=plt.plot(sc.decimate(x[i]['FET1'],5),'-v'+colors[i],label='FET1')
    lines=np.append(lines,l)
    l=plt.plot(sc.decimate(x[i]['FET2'],5),'-x'+colors[i],label='FET2')
    lines=np.append(lines,l)
    l=plt.plot(sc.decimate(x[i]['FET3'],5),'-o'+colors[i],label='FET3')
    lines=np.append(lines,l)

fig.legend(lines)
plt.show()

Zapewni to legendę rozmiaru len(filename)*4 z naprzemiennymi kolorami. Jeśli chcesz podać tylko kolory w pliku, możesz zapisać jedną linię na i.

fig = plt.figure()
lines = []
names = []
colors=['r','b','g','c','m']
for i in range(len(filename)):
    l=plt.plot(sc.decimate(x[i]['PCB'],5),'-+'+colors[i],label="PCB")
    lines=np.append(lines,l)
    names=np.append(names, filename[i][0:7])
    plt.plot(sc.decimate(x[i]['FET1'],5),'-v'+colors[i],label='FET1')
    plt.plot(sc.decimate(x[i]['FET2'],5),'-x'+colors[i],label='FET2')
    plt.plot(sc.decimate(x[i]['FET3'],5),'-o'+colors[i],label='FET3')

fig.legend(lines,labels=names)
plt.show()

EDYTUJ: Trzecią opcją jest też możliwość bezpośredniego zapisania uchwytów legendy dla zbioru pierwszego wiersza i ustawienia ich później. Aby to działało poprawnie, musisz ustawić innych, aby nie mieli legendy. Zakładając, że i tak nie wyświetlasz tych etykiet na swoim wykresie, jest to również opcja.

lines = []
names = []
colors=['r','b','g','c','m']
for i in range(len(filename)):
    plt.plot(sc.decimate(x[i]['PCB'],5),'-+'+colors[i],label="PCB")
    handles, labels = plt.gca().get_legend_handles_labels()
    lines=np.append(lines,handles[0])
    names=np.append(names, filename[i][0:7])
    plt.plot(sc.decimate(x[i]['FET1'],5),'-v'+colors[i],label='_nolegend_')
    plt.plot(sc.decimate(x[i]['FET2'],5),'-x'+colors[i],label='_nolegend_')
    plt.plot(sc.decimate(x[i]['FET3'],5),'-o'+colors[i],label='_nolegend_')

plt.legend(lines,labels=names)
plt.show()
1
ilke444 10 marzec 2020, 19:23