Waarden van een array "oprekken"

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Kayshin
  • Registratie: Juni 2004
  • Laatst online: 09-03-2018

Kayshin

Bl@@T @@P!!!

Topicstarter
Ik zit met het volgende probleem:

Voor een project moet ik in een grafiek een aantal lijnen tekenen. Deze lijnen hebben een x en een y waarde maar ik moet het volgende doen:

Stel ik heb 2 tabellen:
Grafiek 1:
x,y
0,10
1,50
2,40
3,70

Grafiek 2:
x,y
0,20
1,60
2,40
3,90
4,40
5,60
6,70
7,10
8,30
9,40
10,70

Dan krijg ik in mijn grafiek dus 2 lijnen, een die 4 punten heeft en 1 die er 11 heeft.
Echter is dit niet wat ik wil. Ik wil dat de eerste grafiek, die korter is dan de tweede, andere x-waarden krijgt zodat de lengte van de twee grafieken gelijk zijn, de eerste zal wel minder punten hebben, maar dat is niet relevant. Het gaat erom dat ik dan een relatieve grafiek krijg met deze 2 lijnen.
In de eerste grafiek moet ik dus de stapgrootte aanpassen zodat het eerste x-coordinaat 0 blijft, het laatste x-coordinaat 10 wordt en alles er tussenin een nieuwe stapwaarde krijgt.

Ik heb het op deze manier al geprobeerd (in pseudocode voor een programmeeromgeving) maar dit werkt alleen voor zeer kleine grafieken en klopt niet:

Voor elk punt in grafiek 1{
grafiek1.x = grafiek1.X * (lengte van grafiek2 / lengte van grafiek1)
}

Het zou trouwens ook kunnen zijn dat ik in plaats van 2 grafieken er 20 heb en dan moeten alle grafieken zich dus aanpassen naar de langste grafiek die in de verzameling zit.

Een voorbeeld van waarden:
Grafiek 1 oude x-coordinaten:0,1,2,3
Grafiek 2 x-coordinaten:0,1,2,3,4,5
Grafiek 1 nieuwe x-coordinaten: 0,1.66,3.33,5

My personal videoteek: -Clique-; -NMe- is een snol!


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 11:52
Ik weet niet wat jou programmeer omgeving je allemaal toe laat maar iets als

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int grootste = 0;
foreach (grafiek in grafieken)
{
    if (grafiek.size > grootste)
        grootste = grafiek.size
}

foreach (grafiek in grafieken)
{
    for (int i=1;i<grafiek.size -1;i++)
    {
        grafiek[i].X = grafiek[i].X * (grootste / grafiek.size)
    }
    grafiek[i+1].X = grootste;
}

[ Voor 14% gewijzigd door IceM op 05-07-2009 15:34 . Reden: Code aangepast, niet goed gelezen ]

...


Acties:
  • 0 Henk 'm!

  • Mad Marty
  • Registratie: Juni 2003
  • Laatst online: 09:46

Mad Marty

Je bent slimmer als je denkt!

Ik snap geloof ik niet waarom je dit wilt, je hebt x en y coördinaten, wilt een grafiek tekenen, maar niet dat deze grafiek geplot wordt op de coördinaten die je hebt? Ik heb een idee dat je probleem al veel eerder zit, namelijk in hoe je je coördinaten opslaat.

[ Voor 3% gewijzigd door Mad Marty op 05-07-2009 15:31 ]

Rail Away!


Acties:
  • 0 Henk 'm!

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 07-09 11:44

Bergen

Spellingscontroleur

Het eerste en laatste deel van de eerste grafiek wil je dus oprekken zodat ze gelijk komen te staan met de x-coordinaten van de tweede grafiek?

x,y
0,10
1,50
2,40
3,70

Dat zijn 3 delen:
0,10 - 1,50
1,50 - 2,40
2,40 - 3,70

De grafieken beginnen beide al bij x = 0, dus de linker kant hoeven we niet op te rekken. We kijken dus naar het laatste deel. Daarover moet je de richtingscoëfficient (rc) berekenen. Dat doe je met:

(y2 - y1) / (x2 - x1)
(70 - 40) / (3 - 2)
30 / 1 = 30

Dat wil zeggen: telkens als x 1 naar rechts gaat, gaat y 30 omhoog.

Je wilt de meest rechter coordinaat (3, 70) oprekken tot x = 10. Dat is dus 7 stapjes naar rechts. Dat komt overeen met 7 * 30 = 210 stapjes omhoog. De rechter coordinaat wordt dus (10, 280)


[edit]
Aah, dit bedoel je niet. Vergeet bovenstaande maar weer.

[ Voor 4% gewijzigd door Bergen op 05-07-2009 15:35 ]


Acties:
  • 0 Henk 'm!

  • Kayshin
  • Registratie: Juni 2004
  • Laatst online: 09-03-2018

Kayshin

Bl@@T @@P!!!

Topicstarter
IceM schreef op zondag 05 juli 2009 @ 15:29:
Ik weet niet wat jou programmeer omgeving je allemaal toe laat maar iets als

code:
1
2
3
4
5
6
7
8
9
10
11
int grootste = 0;
foreach (grafiek in grafieken)
{
    if (grafiek.size > grootste)
        grootste = grafiek.size
}

foreach (grafiek in grafieken)
{
    grafiek.X = grafiek.X * (grootste / grafiek.X)
}
Wat ik dus had was:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        private List<PointPairList> recalculateScore(List<PointPairList> ppll)
        {
            List<PointPairList> temp = new List<PointPairList>();
            int i = 0;

            foreach (PointPairList ppltemp in ppll)
            {
                temp.Add(ppltemp);
                if (ppltemp.Count > i)
                {
                    i = ppltemp.Count;
                }
            }

            foreach (PointPairList ppltemp2 in temp)
            {
                if (ppltemp2.Count < i)
                {
                    foreach (PointPair pp in ppltemp2)
                    {
                        pp.X = pp.X * (i / ppltemp2.Count);
                    }
                }
            }

            return temp;
        }

En op jou manier verander ik alles behalve het eerste coordinaat naar 7, dat gaat dus niet werken ;)

@ Bergen: Ik heb niks met de y te maken, die moet gewoon hetzelfde blijven, t gaat me alleen om t aanpassen van de x-coordinaten zodat ze verspreid zijn over hetzelfde bereik als de langste grafiek.

[ Voor 10% gewijzigd door Kayshin op 05-07-2009 15:43 ]

My personal videoteek: -Clique-; -NMe- is een snol!


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 11:52
Zie mijn edit, had de TS niet goed gelezen, ik dacht dat je oude code functioneerde.

...


Acties:
  • 0 Henk 'm!

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 07-09 11:44

Bergen

Spellingscontroleur

Nee ik had de laatste regeltjes niet goed gelezen... De code die je hebt ziet er ok uit, behalve dit:

pp.X = pp.X * (i / ppltemp2.Count)));

Lijkt me dat er geen 3 haakjes aan het einde moeten. De pseudocode van IceM komt aardig overeen met je eigen code als ik het zo zie. Wat werkt er dan niet?

Hebben de grafieken trouwens altijd beginpunt 0 of kan dat ook anders zijn?

[ Voor 31% gewijzigd door Bergen op 05-07-2009 15:45 ]


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 11:52
Bergen schreef op zondag 05 juli 2009 @ 15:40:
Nee ik had de laatste regeltjes niet goed gelezen... De code die je hebt ziet er ok uit, behalve dit:

pp.X = pp.X * (i / ppltemp2.Count)));

Lijkt me dat er geen 3 haakjes aan het einde moeten. De pseudocode van IceM komt aardig overeen met je eigen code als ik het zo zie. Wat werkt er dan niet?

Hebben de grafieken trouwens altijd beginpunt 0 of kan dat ook anders zijn?
Ik vermoed dat zijn eerste en laatste items niet kloppen. Aan de hand van zijn code zou dit moeten werken:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        private List<PointPairList> recalculateScore(List<PointPairList> ppll)
        {
            List<PointPairList> temp = new List<PointPairList>();
            int biggestPopulation = 0;

            foreach (PointPairList ppltemp in ppll)
            {
                temp.Add(ppltemp);
                if (ppltemp.Count > biggestPopulation)
                {
                    biggestPopulation = ppltemp.Count;
                }
            }

            foreach (PointPairList ppltemp2 in temp)
            {
                if (ppltemp2.Count < biggestPopulation)
                {
                    // Adjust X coordinates based on biggest population,
                    // skip first and last item
                    for (int i=1; i<ppltemp2.Count - 1; i++) 
                    {
                        ppltemp2[i].X = ppltemp2[i].X * (biggestPopulation / ppltemp2.Count);
                    }
                    
                    // Fix last item
                    ppltemp2[ppltemp2.Count -1].X = biggestPopulation;
                }
            }

            return temp;
        }

...


Acties:
  • 0 Henk 'm!

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 07-09 11:44

Bergen

Spellingscontroleur

Zou niet uit moeten maken, de berekening klopt en de laatste waarde zou automatisch de waarde van biggestPopulation moeten krijgen.

De code gaat echter in de mist als de grootste populatie bijvoorbeeld x-coordaten 0, 1, 3, 3.5, 8 heeft. Dan kun je niet meer naar de aantallen kijken, want dan klopt er niets van de berekening. Je moet op zoek naar de hoogste x-waarde, niet naar het hoogste aantal.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
hoogste_x = 0 /* ervan uitgaande dat ze allemaal boven 0 liggen */

foreach (grafiek in grafieken)
{
    laatste_x = grafiek[grafiek.count - 1].x
    if laatste_x > hoogste_x
    {
        hoogste_x = laatste_x
    }
}

foreach (grafiek in grafieken)
{
    laatste_x = grafiek[grafiek.count - 1].x
    factor = hoogste_x / laatste_x

    for(i = 1; i < grafiek.count; i++)  /* ervan uitgaande dat ze minimaal 2 punten hebben */
    {
        grafiek[i].x = grafiek[i].x * factor
    }
}

Uiteraard moeten die aannames over het aantal punten en de minimale x van 0 wel ergens worden gecheckt in de code.

[ Voor 43% gewijzigd door Bergen op 05-07-2009 16:15 ]


Acties:
  • 0 Henk 'm!

  • Kayshin
  • Registratie: Juni 2004
  • Laatst online: 09-03-2018

Kayshin

Bl@@T @@P!!!

Topicstarter
Het array met grootste populatie heeft altijd een stapgrootte van 1, de andere grafieken moeten aangepast worden.

Ook klopt deze laatste oplossing niet, hij maakt er dit van:
http://img4.imageshack.us/i/voorbeeldgrafiek1.jpg/
terwijl hij dit moet laten zien:
http://img4.imageshack.us/i/voorbeeldgrafiek2.jpg/

[ Voor 49% gewijzigd door Kayshin op 05-07-2009 16:30 ]

My personal videoteek: -Clique-; -NMe- is een snol!


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:20
Als blijkbaar de absolute waarde van x-coördinaten irrelevant is (en er, zoals in je voorbeeld, toch geen schaalverdeling bij de x-as komt te staan) zou ik die x-coördinaten van de punten gewoon naar bereik [0,1] normalizeren, dus per reeks:
  1. Vind de minimum x-coördinaat, en trek die van alle x-coördinaten af.
  2. Vind de maximum x-coördinaat, en deel alle x-coördinanten daar door.
Met stap één zorg je ervoor dat alle reeksen op 0 beginnen (en die stap is dus overbodig als je altijd al met x=0 begint). Met stap twee normaliseer je alles naar bereik [0,1] onder aanname dat je minstens twee punten (met verschillende x-coördinaten) hebt. Vervolgens kun je de boel makkelijk plotten.

Acties:
  • 0 Henk 'm!

  • Kayshin
  • Registratie: Juni 2004
  • Laatst online: 09-03-2018

Kayshin

Bl@@T @@P!!!

Topicstarter
Soultaker schreef op zondag 05 juli 2009 @ 16:54:
Als blijkbaar de absolute waarde van x-coördinaten irrelevant is (en er, zoals in je voorbeeld, toch geen schaalverdeling bij de x-as komt te staan) zou ik die x-coördinaten van de punten gewoon naar bereik [0,1] normalizeren, dus per reeks:
  1. Vind de minimum x-coördinaat, en trek die van alle x-coördinaten af.
  2. Vind de maximum x-coördinaat, en deel alle x-coördinanten daar door.
Met stap één zorg je ervoor dat alle reeksen op 0 beginnen (en die stap is dus overbodig als je altijd al met x=0 begint). Met stap twee normaliseer je alles naar bereik [0,1] onder aanname dat je minstens twee punten (met verschillende x-coördinaten) hebt. Vervolgens kun je de boel makkelijk plotten.
Perfecte oplossing voor mijn probleem! Werkt super! Niet eens aan gedacht om te normaliseren XD

My personal videoteek: -Clique-; -NMe- is een snol!


Acties:
  • 0 Henk 'm!

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 07-09 11:44

Bergen

Spellingscontroleur

Kayshin schreef op zondag 05 juli 2009 @ 16:23:

Ook klopt deze laatste oplossing niet, hij maakt er dit van:
Kun je je code eens posten? Het werkt hier prima namelijk:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
        $grafieken = array();
        $grafieken[] = array(0, 1, 2, 3, 4, 5);
        $grafieken[] = array(0, 1, 2);
        $grafieken[] = array(0, 1, 2, 3, 4);

        $hoogste_x = 0;
        foreach($grafieken as $grafiek)
        {
                $laatste_x = $grafiek[count($grafiek) - 1];
                if ($laatste_x > $hoogste_x)
                {
                        $hoogste_x = $laatste_x;
                }
        }

        echo "Hoogste x: $hoogste_x\n";

        foreach($grafieken as $grafiek)
        {
                $laatste_x = $grafiek[count($grafiek) - 1];
                $factor = $hoogste_x / $laatste_x;
                echo "Laatste x: $laatste_x, factor: $factor\n";

                for($i = 1; $i < count($grafiek); $i++)
                {
                        $grafiek[$i] = $grafiek[$i] * $factor;
                }
                print_r($grafiek);
        }

Output:
$ php test.php
Hoogste x: 5
Laatste x: 5, factor: 1
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
)
Laatste x: 2, factor: 2.5
Array
(
    [0] => 0
    [1] => 2.5
    [2] => 5
)
Laatste x: 4, factor: 1.25
Array
(
    [0] => 0
    [1] => 1.25
    [2] => 2.5
    [3] => 3.75
    [4] => 5
)
Maar de oplossing van Soultaker is ook mooi, op een genormaliseerde reeks kun je vaak gemakkelijker bewerkingen uitvoeren.

[ Voor 3% gewijzigd door Bergen op 05-07-2009 17:19 ]

Pagina: 1