[megoldva] gnuplot / túl sok x tick, ezért a címkék egymásba csúsznak

Fórumok

Sziasztok,

Lenne valakinek arra ötlete, hogyan tudnám valahogy automatikusan szabályozni azt, hogy ha túl sok x tick van, akkor kevesebbet jelenítsen meg a gnuplot? Mert használok címkéket, és így egybecsúsznak a címkék - lévén súl sűrűn jelöli meg az x tick-eket.

Tehát a függvényt megjelenítheti az összes elérhető adat felhasználásával, csak a tick-eknek szeretnék egy max limit-et adni - ha lehetne, akkor a köztük lévő hely minimális meghatározásával.

Egy min spacing beállítást keresnék az xtics-hez.

Jelenleg ezekkel a beállításokkal használom (első oszlop egy idő bélyeg, a második az adat):

set xtics rotate
set xdata time
set timefmt '%Y-%m-%d'
set format x '%Y-%m-%d'
plot data.csv using 1:2:xticlabels(1) title '' with lines lw 5 lt 1 lc 1

Erre próbálok rákeresni sikertelenül.

Itt szintén ezt a problémát írják le. Itt pedig szintén ezt kérdezik.

Hozzászólások

Még ami a problémát adja, hogy mivel az X tengelynek a dátumot jelenítem meg, így a "set xtics /incr/" paranccsal nem tudok egyszerű numerikus lépésközt beállítani.

Nem jó.

Az a gond, hogy mivel megjelölöm az X-et mint idő fajta adat, ezért ő a tengelyen széthúzza, és "kitölti" a hiányzó időkkel. Ekkor a tick-ek nem egyenletes eloszlásúak, és nem működik jól a gnuplot auto tick spacing-je.

Most olyan jutott eszembe, hogy mi van ha epoch time-mal rajzoltatom meg a postscript fájlt, majd az eredményben (fájlban) kicserélem az epoch időket (amik immáron a cimkék rajta).

Egyszerűen nem találok jobb megoldást.

(Két oszlop, tab karakterrel elválasztva):

1990-03-04 1332
1990-09-01 3323
1991-12-28 23322
1992-04-09 33276
1992-07-23 3324
1994-06-05 83320
1994-11-12 33258
1995-07-05 53327
1995-07-26 24332
1996-09-27 32332
1998-09-21 48332
1999-09-15 13320
1999-10-22 84332
2001-01-28 70332
2002-01-12 13321
2002-04-13 33288
2003-04-03 33215
2003-06-15 63326
2005-05-27 42332
2006-09-23 73323
2008-09-17 53320
2009-05-02 13320

Ez a bemenet ezt eredményezi.

Szerk.: Tehát mivel pozícionálja az idő cimkéket, ezért egybecsúsznak. Azt szeretném hogy ha nagyon közelre kerülnek, akkor azt ne mutassa amivel egybe lógna vagy átfednék egymást.

set xtics autofreq -kel sem nez ki jobban?

Sajnos nem. Egyéként jó a gnuplot alapműködése és automatikus beállításai, csupán ugye most az automatikusan "széthúzott" idő miatt ez borul. Tehát ha pl. van 2 oszlopom, első oszlop dátum, másik adat, és a 3 érték közül 1 nagyon "távol" van, 2 meg időben nagyon közel, akkor ugye mindenképpen egymásra csúsznának ha a képernyőn adott pixel méretben ábrázoljuk őket. Pl.

2001-01-01 1
2001-01-02 2
2067-01-01 3

Itt sajnos nagyon közel kerül az első kettő érték- azt hittem majd gnuplot ilyenkor itt is átlagol és csak 1 cimkét fogok látni. Ugye egy 10 ezres nagyságrendű adatnál fekete cík van a cimkék helyén a túl sűrű megjelenítés miatt.

Arra is gondoltam hogy a bemeneti adatokat én átdolgozom, de ugye az meg sokkal lassab. Eleve SQL db-ből veszem (ez gyors), majd gnuplotnak beadtam (ez is gyors). De ha nekem kell végig átlagolnom az egész cuccot, hogy pl. 10 ezer adatból legyen max 100 darab, akkor az már nagyon kókány megoldás. Azt hittem lesz valami beállítása a gnuplotnak.

Nem értem a problémát.

Ha elhagyod az xticlabels(1)-et, akkor szépen két évenként rak egy címkét (a feljebb posztolt példaadatokkal).

Ha úgyis fel kell adnod azt az elvet, hogy minden adathoz teszel címkét, mert túl sok lenne és nem lenne olvasható, akkor annak sincs értelme, hogy csak néhányhoz teszel, tehát az automatikus, egyenletes beosztású címkézés teljesen jó megoldás.

Ha mégis valamiért ragaszkodsz ahhoz, hogy a címkék mindig valamelyik adatpontra essenek, de ne mindegyikre, akkor sajnos neked kell szűrnöd őket, a gnuplot magától nem fogja. (Az olvasóban pedig fel fog merülni a kérdés, hogy miért pont azokhoz a pontokhoz tettél címkét.)

Ha úgyis valami scripttel exportálsz SQl-ből, akkor a script megteheti azt, hogy figyeli, hogy elegendő idő "eltelt" a legutóbbi címkézett pont óta, és ha igen, akkor a célfájl harmadik oszlopába is beírja az időbélyeget.
A gnuplotban pedig xticlabel(3)-at használsz (1) helyett. Az elegendő idő a kép és a font méretétől (továbbá ízléstől) függ, kísérletezni kell a megállapításához.

Közben máshogy fogalmazódott meg bennem amit szeretnék. Ezt leírom megint:

Igazából nem szeretném hogy az idő vonalon széthúzza a beosztást az idő oszlopom adatai alapján. Egy nagyon egyszerű dolgot szeretnék: ábrázolja az adat oszlopom értékeit mintha nem lenne dátum oszlopom, és olvasható távolságban látszódjanak a hozzá tartozó idő cimkék. De nem kell arányos távolságban lenniük.

Ezt nem csinálja meg alapból nekem anélkül hogy arányosan széthúzná az X tic-eket.

A kérdésedre válasz: azért jó nekem az hogy nem minden ponthoz van cimke, mert a látható cimkék idő értékéből látszik már hogy milyen időpont körül lehet kiugrás az adatokban. Tehát egyáltalán nem kellene mindegyikhez.

Ezt az egyszerű dolgot hogy tudnám megtenni? Ugye ha csak 1 oszlopot dolgozok fel, akkor ábrázolja az adatot, és automatikus módon osztja fel az X tengelyt és ábrázolja a sorszámát az adatnak cimkeként. Én azt szeretném, hogy ugyanígy, csak nem a sorszámát (hogy hányadik adat), hanem az oda tartozó idő cimkét tegye oda. Úgyis dátum szerint sorrendben van az adat. Tehát egy nem releváns kitalált sorszámnál mindenképpen többet mond egy dátum, amihez már nagyjából lehet viszonyítani.

Akinek meg nagyobb felbontású ábra kell, az majd megjelenít kevesebb adatot és kész.

Köszi.

Most már végképp nem értem, hogy miért nem jó neked az, amit alapból, xticlabels nélkül csinál.

A második bekezdésben azt írod, hogy nem jó, ha "széthúzza a beosztást", ami nem tudom, mit jelent nálad - azt, hogy nem megfelelő az automatikus, egyenletes közű címkézés?

Az ötödikben ellenben azt mondod, hogy "Ugye ha csak 1 oszlopot dolgozok fel, akkor ábrázolja az adatot, és automatikus módon osztja fel az X tengelyt és ábrázolja a sorszámát az adatnak cimkeként. Én azt szeretném, hogy ugyanígy".

A negyedik bekezdésben pedig leírod, hogy tulajdonképpen mi a célod a grafikonnal:
hogy a kiugró értékek legyenek időbélyeggel jelölve.

Ha elég, hogy csak nagyjából legyenek jelölve, akkor az xticlabels nélküli, egyenletes eloszlású skála tökéletesen megfelelő. Bárki, aki már látott kilométerórát az autóban, le tudja róla olvasni, hogy nagyjából hol vannak a kiugró értékek.

Ha viszont explicite jelölni akarod a kiugró értékeket, akkor egy nemtriviális jelfeldogozási feladatot kell megoldanod, és pontosan meg kell mondanod a gnuplotnak, hogy melyikeket címkézze. Magától nem fogja tudni, többek között azért nem, mert nem tudhatja, hogy nálad mi számít kiugró értéknek.

Itt látható, hogy dolgozza fel az első oszlopot gnuplot, ha nem adom meg neki a dátum oszlopot, hanem csak a nyers számokat. Az Y tengelyen az adatok értékei látszanak, míg az X tengelyen a sorszámuk, hogy hányadik volt az aktuális ponthoz tartozó adat. Ezt gnuplot teszi hozzá, ilyen értékem nekem nem volt eredetileg, hanem csak egyetlen oszlop.

Eredetileg tartozik az adataimhoz dátum. A sorszámok helyett szeretném az oda tartozó dátumot kiiratni. Pont ugyanígy, semmi változtatás nem kellene, csak a gnuplot által generált automatikus sorszám helyett legyen ott az ahhoz a ponthoz tartozó dátum. Ennyi. De lehetne ez egy név is a második oszlopban, nem feltétlen dátum, hanem akármi.

Ezt meg lehet vajon csinálni?

Ezen a grafikonon lényegében az van, hogy minden 50. pont kap címkét. És mivel a sorszám szerint ábrázolod az y értékeket, a címkék pont egyenletes eloszlásúak lesznek. De ha te áttérsz arra, hogy az idő legyen az x tengelyen, de továbbra is minden 50. legyen címkézve, akkor természetesen semmi nem garantálja, hogy nem fognak egymásra csúszni a címkék.*

Ha az a célod, hogy az idő legyen az x tengelyen és a grafikonon egyenletesen legyenek elosztva a címkék, akkor a gnuplot automatikus, egyenletes beosztása tökéletesen megfelelő. Igaz, ekkor a címkék nem a konkrét adatpontok dátumainak fognak megfelelni, de szerintem ez jól is van így. Az autó kilométeróráján is egyenletes beosztású skála van, önkényes értékekkel (20, 40, 60...), mégis mindenki le tudja olvasni.

Ha az a cél, hogy az idő legyen az x tengelyen és mindenképpen adatpontokra essenek a címkék, továbbá nagyjából egyenletes eloszlásúak legyenek, akkor ismét egy nemtriviális jelfeldolgozási feladatot kell megoldanod, mielőtt az adatokat továbbadod a gnuplotnak, és semmi sem garantálja, hogy találni is fogsz megfelelő pontokat.

Ha csak annyi kell, hogy ne csússzanak egymásra a címkék, akkor fentebb leírtam, hogy lenne célszerű szűrni.

* Ha tényleg ezt akarod, akkor némi trükközéssel megoldható:

set yrange [0:*]
set xtics rotate
set xdata time
set timefmt '%Y-%m-%d'
set format x '%Y-%m-%d'

plot 'data.txt' u 1:2 w lines lw 5 lt 1 lc 1, '' u 1:(-100000):xticlabels(1) every 50 w dots

using 1:2:xticlabels(1)

helyett

using 2:xticlabels(1)

-re volt szükségem.

Szerk.: Sajnos mégsem jó. Ezzel megoldom azt, hogy nem időként kezeli és nem arányosan helyezi el a dátum címkéket egy képzeletbeli időegyenes alapján - viszont továbbra is annyi címke van, amennyi bemeneti adat és a sok egymásra printelt címkékből egy fekete csík lesz.

Egyre nagyobb a gyanúm, hogy olyat akarsz, amit a gnuplot nem tud. Vagy félreértelek.

Ez nem az amire gondolsz, de lehet hogy megoldás lehet:

plot "a.dat" using 1:2:1 with labels, "a.dat" using 1:2 with lines

Esetleg:

plot "a.dat" using 1:2:1 with labels rotate by 60, "a.dat" using 1:2 with lines

-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.

Ez ötletesnek tűnik, hogy 2x rajzoljak.

Igazából kettőtök ötletéből arra gondoltam, hogy kirajzolom x labelek nélkül az adatokat 1 oszlop felhasználásával, majd rárajzolom az x label-eket az "every" parancs felhasználásával - így az ábrában minden adat fel lesz használva (every paranccsal ugye nem lenne) és a labelek is jók lehetnek. Ugye az adatok teljes darabszámát tudom. Legfeljebb azt csinálom, hogy ha a bemeneti adatok száma egy max értéknél nagyobb, akkor visszaosztom a szükséges értéket és megadom az every paranccsal, hogy így bizonyos számnál ne rajzolódjon ki több cimke.

Eljátszok vele este és megírom az eredményt majd. Köszi.

Tehat ragaszkodsz hozza, hogy az idoskala ne egyenletes legyen, tehat neha 1 honap 1 pixel, aztan 30 masodperc egy pixel. Ez szerintem zavarni fog mindenkit aki egyszer is megprobalja leolvasni, de te tudod.

En igy csinalnam:

1. adatbazisbol valahogy igy kerdezem le:

Adatbazis:


idobelyeg | adat
---------------
1990-03-04 1332
1990-09-01 3323
1991-12-28 23322
1992-04-09 33276
1992-07-23 3324
1994-06-05 83320
1994-11-12 33258
1995-07-05 53327

SELECT
 CASE
    -- legmagasabb 3 adat kiugro, kell tengelyfelirat 
    WHEN adat IN (SELECT adat FROM tabla ORDER BY adat DESC LIMIT 3)
      THEN idobelyeg
    -- tobbi adathoz nem kell tengelyfelirat (ures string)
    ELSE ''
 END AS cimke,
 adat
FROM
 tabla
ORDER BY
 idobelyeg
;

Ezt kapod:


cimke     | adat
---------------
           1332
           3323
           23322
1992-04-09 33276
           3324
1994-06-05 83320
           33258
1995-07-05 53327

2. gnuplot megrajzolja ugy, hogy elso oszlop x tengelyre, masodik y-ra. Ne datum/idokent ertelmeztesd az elso oszlopot, csak sima stringkent.

Leolvasás szempontjából igazad lenne, de 10 másik ok miatt letettem erről. Egyetlen célt szolgál az idő címke amúgy is: hogy jobban be lehessen határolni az adat táblában egy adott rész helyét. Semmi többet.

Ún. egyenletes időskálával meg úgyis hiányozhatnának adatok, és mint feljebb írtam, lehet hogy lenne néhány pár percen belüli érték, meg egy 30 évvel későbbi. Ezt gnuplot egy görbével kitöltené, de ez meg ott csalóka, hogy a kitöltött helyen igazából nincs is adat, csak burkoló görbe. Ez ugyanúgy becsapós, mert vizuálisan érzékeltet egy hamis bemenet miatti eredményt. Habár visszatérve, megint csak az a lényeg, hogy a meglévő táblánk adatai alapján a valós értékeket lássuk vizuálisan - ez csak egy segéd eszköz.

Meg még sok másik okom van, csak több oldal lenne leírni :)

Köszi a tippet, átnézem.

"Ezt gnuplot egy görbével kitöltené, de ez meg ott csalóka, hogy a kitöltött helyen igazából nincs is adat, csak burkoló görbe. Ez ugyanúgy becsapós, mert vizuálisan érzékeltet egy hamis bemenet miatti eredményt"

Egy ötlet: xticlabels nélküli, egyszerű, egyenletes időskála automatikus címkékkel (akár a hónap-nap is elhagyható róluk, hiszen mint írod, csak nagyjábóli behatárolásra kellenek), viszont lines helyett linespoints, mint ábrázolási stílus. Ez összeköti a pontokat egy vonallal, érzékeltetve, hogy mégiscsak egy folytonos adatsorról van szó, de tesz egy-egy jelet oda, ahol ténylegesen van adatpont. (Ez nem mutat annyira jól, ha nagyon sok pont van, bár még ott is lehet trükközni, hogy vékony vonalat és kis jelméretet használsz (lw 0.1 ps 0.5 vagy hasonló), így kvázi úgy látszik, hogy ahol van adat, ott vastagabb a vonal az egybefolyó kis szimbólumok miatt).

Jó ötlet, nekem is megfordult a fejemben a kereszt vagy kicsi kör (asszem ilyet tud) az adat pontnál. Viszont vonal típusra a "smooth csplines" jött be nekem legjobban kevés és sok adatnál is az adat milyenségének visszaadására. Ennél viszont nem lesz jó az adatpont megjelölés sok adatnál. De kevés adatnál (pl. <100) elgondolkodok rajt, mert javíthatja a görbe által vissza adott információ minőségét biztos.

Na várjál - a smooth csplines azt csinálja, hogy az adataidra illeszt egy folytonos, viszonylag sima függvényt, aztán az eredeti adataidat ELDOBJA, és az illesztett függvényt mintavételezi szabályos időközönként (a minták számát a set samples paranccsal lehet állítani).

Tehát te nem is az eredeti adataidat ábrázolod. Akkor meg minek vacakolni az eredeti időbélyegekkel?
Sőt, amit akarsz, az egyenesen az olvasó megtévesztése: azt hiszi, hogy a pontos időbélyeg helyén leolvasható y érték az, amit a műszered (vagy mittoménmid) mért abban az időpontban, pedig nem, mert valójában te egy simított görbét mutatsz neki. A simított görbén lévő maximumoknak sem a helye, sem az értéke nem fog egybeesni a valódi adatsor maximumainak helyével ill. értékével.

Igaz amit mondasz - sok adat esetén. De pl. 10 ezer adatot sehogy nem tudsz ábrázolni megfelelően kevés pixelen.

A csplines azért jó, mert látható lesz, hogy milyen az adat nagyjából. Kevés adatnál meg valós értéket mutat a görbe.

Minden más típusnál sokkal messzebb van a valóságtól IMHO.

Ja értem, a kiugró értékekhez jelenítenéd meg. Viszont itt sem lenne ezek szerint garantálva 2 dolog ha jól gondolom:

1) egyenletes legyen a felosztás a cimkék közti távolságot illetően

_ÉS_

2) minden bemeneti adat fel legyen használva a gnuplot által előállított görbéhez

Szerk.: magyarázat, hogy miért nem jók a kiszámíthatatlanul túl közeli dátum cimkék az átfedésen kívül:

- ha sima unique típusú görbével csinálom, akkor kevesebb információt fog hordozni a végeredmény, mert sok adatnál egy teli téglalap lesz a sok egymásra rajzolt egyenes miatt
- a bezier típus pedig sima burkoló görbét csinál, nem lesznek láthatók a bemeneti adatoknál az ingadozás - sok adatnál főleg nem
- csp vonalnál ez látható jól, de ennek meg az a gondja, hogy a túl közeli és túl nagyon ingadozó részek miatt kilövi a görbe tetejét túl magasra

A fenti dologgal minden megoldódik.

1. Nem ertelmezheto az egyenletes felosztas az x cimkeknel, mert nem fuggvenyt abrazolsz. Az x tengelyed nem linearisan vagy logaritmikusan stb. novekszik, hanem random ugrasokkal.
Meg amugy is a kiugro adatokhoz akartal cimket, hogy le lehessen olvasni.

Hogy vizualisan nezzen ki jol a skala? Dehat az csak szemfenyvesztes, a 2012-10-01 mellett egy pixellel lehet 2012-10-02 es 2222-12-31 is. Alig hordoz informaciot egy egy felirat, viszont atveri az agyat a cimke nelkuli pontokra vonatkozoan.

2. Minden bemeneti adatot felhasznal, ez a lenyeg. Csak az x tengelyre a felirat az adatok tobbsegenel ures string, igy nem folyik ossze olvashatatlanna.

Osszessegeben: az az erzesem, hogy "forditva ulod a lovat". Vizualisan szep grafikont akarsz, ami nagyon helyes, viszont mar reg nem a valosagot abrazolod. Pl: le akarsz olvasni bizonyos (kiugro) adatokat, de gorbet illesztesz amin pont nem latszanak a konkret adatok. Egyaltalan miert akarod a pontokat osszekotni? Igaz az, hogy a valosagban a ket idopont kozott az adat is a ket "meres" kozott mozog? Pl. homerseklet nem tul ritkan merve.

Még egy megjegyzés:

A dátumoknak esetemben egyébként nem célja érzékeltetni egy folyamatosságot. Ezért is vetettem el a gnuplot által alapból időegyenesre való illesztést.

Ezek olyan adatok, amilyeneket létrehozol: dátum, ma, kék az ég - 1 év múlva egy bejegyzés, hogy ma szintén kék vagy felhős. Ezért közelít jobban a valósághoz az, hogy minden adatot felhasználok, és az adathoz odabiggyesztem az oda tartozó dátum cimkét. Mert az adat táblában is pontosan ez van, és cél a valóság közelítése.

És mivel nem lehet mindig minden adatnál odatenni a cimkét a túl sok bemenetnél, ezért a kevés is jobb mint a gnuplot által odatett növekvő számok, amelyeknek semmihez semmi köze.

Na végre 3 nap után sikerült megoldanom a dolgot. Nem számítottam rá hogy ennyire durva lesz, de persze gyors megoldást akartam, és ennek ára van :)

ironcat és kikuchiyo válaszai segítettek el a megoldásig. Köszi!

Azt kell tudni, hogy az adat görbe alá mindig odateszek egy zero függvényt szaggatott vonallal, hogy látszódjon a nulla vonal helyzete. Ez is segít az ábra minél jobb leolvasásában.

Ugye azt szerettem volna, hogy az ábrázolt adatom alá odarkja gnuplot az adataimhoz tartozó dátum cimkéket. Az volt a gond ezzel, hogy gnuplot egy valós idő egyenesen széthúzza alapból az értékeket, és így nem egyenletes a cimkék eloszlása, amely az általam feljebb leírt problémákat okozza. Azt is leírtam feljebb, hogy miért nem kell nekem ez az idő széthúzás.

Végül az lett a megoldás, hogy a dátum címkéimet nem az adataimhoz párosítom hozzá és nem ezzel együtt rajzolom ki, hanem mindezt a nulla vonallal teszem meg.

(Idevonatkozó gnuplot parancs a "plot adat.csv" után: "using 2:xticlabels(1)")

Tehát a dátum / adat oszlopom helyett egy dátum / 0 oszlopokkal teli .csv fájlt hozok létre és ezzel etetem meg a gnuplot-ot. Annyi még itt a trükk, hogy a .csv fájl létrehozása előtt az egész tömbömön végigmegyek 1x és csak néhány címkét hagyok meg, a többi helyére üres karaktert írok. Ezt egy általam max konstanssal határozom meg: ha a dátum cimkék száma ennél kisebb, akkor nem nyúlok hozzá - míg ha nagyobb, akkor visszaosztom és úgy ritkítom meg, hogy a megmaradók száma ne legyen több ennél a konstansnál. Illetve a legelsőt és legutolsót mindenképpen meghagyom.

Illetve még egy csavar: a végső ábrában nem látszott soha az utolsó cimke, ezért a tömbhöz még egy üres elemet hozzáadok.

Ebből állt össze végül a helyes megoldás. Így meghatároztam a megjelenő címkék maximális számát és a megfelelő helyükre is kerültek, mivel ha mindkét bemenet száma megegyezik, akkor egymással passzolnak - míg ha nem, akkor az xrange értéke egymáshoz képest különböző lesz. De ez megoldotta.

Nem számítottam ekkora szívásra, szerintem kb. olyan több mint 20 órát csesztem el erre, de most már jó.