Predavanje 11: Glava 30,31

FlipView[{Text[Style[" Branko Urošević, imqfbrankourosevic@gmail.com ",20,"Text",Italic]],Text[Style[" Faculty of Economics, University of Belgrade, NBS and CESIfo Munich",20,"Text", Italic]]}]

30. Preuređenje lista

Uvod u preuređenje lista

Preuređenje lista je ključno u radu sa podacima o od njega veoma zavisi šta se od njih dobije. Možemo da je predstavimo grafički na primer ovako:

{{1,2},{3,4},{5,6},{7,8},{9,10}}//ListLinePlot

Imali bismo jedan grafik koji spaja pomoću linije te tačke. A šta bi se desilo ako bismo listu transponovali? Onda bismo imali dva grafika:

Transpose[{{1,2},{3,4},{5,6},{7,8},{9,10}}]

U 2d, transponovanje se može napisati pomoću EsctrEsc. Vidimo da isti podaci, kada se transponuju, dobijaju sasvim novi smisao.

{{1,2},{3,4},{5,6},{7,8},{9,10}}\[Transpose]

Transponovanje

Primetimo da sada imamo dve liste brojeva, a ne jednu (svaka od lista ima x koordinate sada implicitno 1,2,3,4...)

{{1,2},{3,4},{5,6},{7,8},{9,10}}\[Transpose]//ListLinePlot

Transpose[{{1,2},{3,4},{5,6},{7,8},{9,10}}]//MatrixForm

Transpose pretvara ove dve podliste u uredjene parove:

Transpose[{{1,3,5,7,9},{2,4,6,8,10}}]//MatrixForm

Particija (Partition) od početne liste pravi liste složenije strukture

Partition menja strukturu liste i razbija je na blokove određene veličine. Razbijte listu od 12 elementata u podliste veličine 3. Dobićete matricu sa 4 reda i tri kolone:

Range[12]

Partition[Range[12],3]

Grid[%]

Razbijte listu karaktera pomoću Partition kako biste ih prikazali u gridu:

Grid[Partition[Characters["An array of text made in the Wolfram Language"],7],Frame->All]

Još o Partition

Ako mu se drugačije ne naredi, Partition pravi blokove koji se ne preklapaju. Ali, nekad je korisno dozvoliti delimično preklapanje ili offset. Partition listu u blokove veličine 3 sa offsetom 1:

Partition[Range[10],3,1]

Uporedimo to sa

Partition[Range[10],3]

Evo još primera:

Grid[Partition[Characters["Wolfram Language"],12,1],Frame->All]

Flatten: uprošćavanje složene liste

Partition uzima prostije liste i razbija ih na podliste. Flatten “poravnjava” podliste, u potpunosti ili delimično, odnosno od složenijih lista pravi prostije. Napravite listu cifara sukcesivnih celih brojeva:

IntegerDigits/@Range[20]

Ukoliko koristimo Flatten bez dodatnih opcija, dobićemo uvek prostu listu koja sadrži sve elemente onim redom kojim se pojavljuju u složenoj listi:

Flatten[IntegerDigits/@Range[20]]

ListLinePlot[Flatten[IntegerDigits/@Range[100]],PlotTheme->"Detailed"]

Još o Flatten

Flatten normalno poravnjava do kraja, do potpuno proste liste, bez podlista. Ali često to ne želimo nego hoćemo da se poravnja samo do određenog nivoa (nivo je Level). Ovako pravimo tabelu 4×4 table u kojoj je svaki element takođe lista:

Pretpostavimo da želimo da napravimo uređene trojke koje se sastoje od celih brojeva od 1 do 10 kao i kvadratnog korena od sume njihovih kvadrata. Kako to možemo da uradimo? Koristeći Table dobijamo

Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,10},{j,10}]

Da bismo dobili od te složene liste uređene trojke, treba da Flatten za jedan nivo

Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,10},{j,10}],1]

Vidimo da je poslednji broj nekada ceo broj. To su takozvane Pitagorine trojke.

Split razbija prostu listu po određenom kriterijum

Ukoliko ne zadamo dodatnu funkciju na kraju Split pravi takozvane runs istih elemenata.

Split[{1,1,1,2,2,1,1,3,1,1,1,2}]

Vidimo da Split napravi grupu elementa 1 tri puta. Onda dolazi do prekida u tom elementu kad se pojavi u nizu element 2 koji se ponavlja 2 puta itd. Split može i da se kontroliše dodatnom čistom funkcijom na kraju. Razmotrimo listu prvih 20 prostih brojeva

Array[Prime,20]

Razbijmo u podliste kod kojih se sukcesivna dva člana ne razlikuju za manje od 4.

Split[Array[Prime,20],#2-#1<4&]

Gather i GatherBy

Gather, sa druge strane, skuplja iste elemente gde god da su bili u listi:

Gather[{1,1,1,2,2,1,1,3,1,1,1,2}]

Ovako možemo da skupimo na jedno mesto uređene parove koji imaju isti prvi element (recimo a, ili b)

Gather[{{a,1},{b,1},{a,2},{d,1},{b,3}},First[#1]==First[#2]&]

GatherBy skuplja elemente na osnovu rezultata aplikacije neke čiste funkcije. Ovde skupljamo elementa na osnovu LetterQ, tako da razbijamo skup karaktera na one koji su slova i one koji nisu:

Characters["It's true that 2+2 is equal to 4!"]

GatherBy[Characters["It's true that 2+2 is equal to 4!"],LetterQ]

Ovako jednostavnije možemo da uradimo ono od malopre

GatherBy[{{a,1},{b,1},{a,2},{d,1},{b,3}},First[#]&]

SortBy sortira na osnovu rezultata primene neke funkcije

SortBy sortira na osnovu rezultata primene neke funkcije:

Table[IntegerDigits[2^n],{n,10}]

Ovde SortBy sortira na na osnovu prvog elementa u svakoj od podlisti:

SortBy[Table[IntegerDigits[2^n],{n,10}],First]

SortBy[{{a,1},{b,1},{a,2},{d,1},{b,3}},First]

SortBy[{{a,1},{b,1},{a,2},{d,1},{b,3}},Last]

Union (unija skupova) i Join

Union spaja više lista i izbacuje sve ponovljene elemente (to je unija skupova). Takođe, ako primenimo samo na jednu listu, izbaciju sve ponovljene elemente.

Union[{1,9,5,3,1,4,3,1,3,3,5,3,9}]

Union[{1,2,3},{2,3,5}]

Union možemo predstaviti u 2d preko  Esc un Esc

{1,2,3}⋃{2,3,5}

U slučaju Join ništa se ne izbacuje:

Join[{1,2,3},{2,3,5}]

Intersection (presek skupova) i Complement (razlika skupova)

Naći elemente koji su zajednički za grupu lista (presek skupova):

Intersection[{2,1,3,7,9},{4,5,1,2,3,3},{3,1,2,8}]

Intersection može da se predstavi preko 2d simbola sa Esc inter Esc

Dakle, prethodna operacija može ekvivalentno da se napiše i kao:

{2,1,3,7,9}⋂{4,5,1,2,3,3}⋂{3,1,2,8}

Razlika u skupovima (komplement). Naći elemente koji su u prvom skupu ali ne i u drugom:

Complement[{4,5,1,2,3,3},{3,1,2,8}]

Primeri sa azbukama

Intersection[Alphabet["Croatian"],Alphabet["Swedish"]]

ili

Alphabet["Croatian"]⋂Alphabet["Swedish"]

A koja slova su zajednička u hrvatskom i engleskom?

Intersection[Alphabet["Croatian"],Alphabet["English"]]

Evo slova koja se pojavljuju u švedskom ali ne i u engleskom i obrnuto:

Complement[Alphabet["Swedish"],Alphabet["English"]]

Complement[Alphabet["English"],Alphabet["Swedish"]]

Ubacivanje ponovljenog elemenata u listu: Riffle

Pretpostavimo da želimo da ubacimo jedan isti element između svaka dva elementa liste. To se dobija pomoću Riffle:

Riffle[{1,2,3,4,5},x]

Riffle “--“ u listu karaktera:

Riffle[Characters["WOLFRAM"],"--"]

StringJoin sve karaktere u jedan string:

StringJoin[Riffle[Characters["WOLFRAM"],"--"]]

Stvaranje lista od neke grupe elemenata: Permutations, Subsets

Pretpostavimo da imate neke elemente i da od njih hoćete da napravite liste na neki način.

Permutations vam daje sve permutacije neke grupe elemenata (u svakoj učestvuju svi elementi). Tu je poredak važan i nema ponavljanja. Generišemo listu od 3!=3×2×1=6 mogućih permutacija 3 elementa:

Permutations[{Red,Green,Blue}]

Umesto toga mogu da nas interesuje skup svih podskupova koje možemo konstruisati od ta tri elementa. Njih će biti (2^3)=8. Dobijamo ih putem Subsets. To je takozvani Power Set skupa {Red,Green,Blue}

Subsets[{Red,Green,Blue}]

Tu nam nije važan poredak u podskupu nego samo koji su elementi u njemu. Šta ako želimo samo podskupove koji imaju 2 člana? U tom slučaju:

Subsets[{Red,Green,Blue},{2}]

Još o Subsets

Evo zanimljive primene Subsets u finansijama. Pretpostavimo da imamo mandat da od 5 akcija izaberemo samo 3 za našu investiciju. Akcije kojima raspolažemo su

{"Microsoft","IBM","Apple","Google","ATT"}

U koje akcije možemo da investiramo? Subsets daje odgovor na to pitanje:

Subsets[{"Microsoft","IBM","Apple","Google","ATT"},{3}]

Tuples

Tuples generiše sve kombinacije ukazanih dimenzija (uz moguće ponavljanje). Tu je, za razliku od Subsets, poredak važan.

Generisati listu mogućih uređenih trojki sastavljenu od Red i Green:

Tuples[{Red,Green},3]

Kao primer primene možemo da razmotrimo binomni model za akcije. Naime, neka akcije može ići ili na gore za faktor u, ili na dole za faktor d. Kakve su moguće kombinacije u 4 koraka šta sve može da se desi sa akcijom?

Tuples[{u,d},4]

Slučajni izbor elemenata sa ponavljanjem (RandomChoice)

RandomChoice nam omogućava da napravimo slučajan izbor iz grupe elemenata:

Napravite slučajni izbor iz liste jednom:

RandomChoice[{Red,Green,Blue}]

Napravite 100 slučajnih izbora iz liste:

RandomChoice[{Red,Green,Blue},100]

Napravimo listu dimenzija 5 x 3 sa slučajnim izborima sa ove liste:

RandomChoice[{Red,Green,Blue},{5,3}]

Slučajan uzorak bez ponavljanja (RandomSample)

Primetimo da kod RandomChoice možemo ponavljanjem dobite više puta jedan isti element. To odgovara izboru kuglica kod verovatnoće sa ponavljanjem. Međutim, nekad želimo da izbor pravimo bez ponavljanja (drugim rečima, ne vraćamo kuglicu nazad u urnu).

RandomSample slučajno bira elemente iz liste, nikada ne birajući dva puta jedan isti element. Izabrati 20 elemenata od 1 do 100:

RandomSample[Range[100],20]

Naravno, bez ponavljanja ne možemo od 100 različitih elemenata izabrati 101. Drugim rečima, ukoliko nema ponavljanja, moramo da biramo manje elemenata u uzorku nego što ih imamo u celini.

RandomSample[Range[100],101]

Dodavanje zaglavlja pomoću Prepend i dodavanje novih redova pomoću Append

Kada radimo sa podacima, korisno je dodati zaglavlje pomoću Prepend:

data={{1.2,0.4},{0.4,1.3},{-2.1,3}};heading={"Column1","Column2"};

Prepend[data,heading]

Prepend[data,heading]//Grid

Pretpostavimo da želimo da dodamo kasnije rezultat još jednog merenja na kraju. To radimo sa Append funkcijom:

Append[Prepend[data,heading],{2.,0.1}]

Append[Prepend[data,heading],{2.,0.1}]//Grid

31. Ekstrakcija delova liste

Izbor jednog elementa liste pomoću Part

Part nam omogućava da izaberemo deo neke liste. Izabrati element 2 iz liste:

Part[{a,b,c,d,e,f,g},2]

[[...]]  je alternativni zapis za to isto. Koristi [[2]] da izabereš drugi element:

{a,b,c,d,e,f,g}[[2]]

Negativni broj meri od kraja liste:

{a,b,c,d,e,f,g}[[-2]]

Izbor više elemenata liste pomoću Part

Umesto samo jednog možemo da izaberemo više elemenata: ovde izaberimo 2., 4. and 5. element:

{a,b,c,d,e,f,g}[[{2,4,5}]]

U punoj formi

Part[{a,b,c,d,e,f,g},{2,4,5}]

Part možemo da koristimo i da izaberemo više uzastopnih elemenata. Izaberimo sve elemente od 2. do 5:

{a,b,c,d,e,f,g}[[2;;5]]

ili u FullForm:

Part[{a,b,c,d,e,f,g},Range[2,5]]

Izbacivanje elemenata liste pomoću Drop

Još jedna funkcija koja se koristi često je Drop. Dozvoljava da se neki element ili grupa elemenata izbaci. Drop prva dva ili poslednja dva elementa iz liste:

Drop[{1,2,3,4,5},2]

Drop[{1,2,3,4,5},-2]

Ukoliko imamo složenu listu Drop izbacuje odgovarajuće podliste (redove):

Drop[{{1,2,3,5},{3,2},{-1,2}},1]

A ovako izbacujemo elemente od 2 do 4:

Drop[Range[10],{2,4}]

Ostavljanje grupe elemenata liste pomoću Take (komplementarno sa Drop)

Take je na neki način komplementarna sa Drop. Ovde uzimamo prva 4 ili poslednja 3 elementa:

Take[{a,b,c,d,f},4]

Take[{a,b,c,d,f},-3]

Ovako uzimamo elemente od 2 do 4.

Take[{a,b,c,d,f},{2,4}]

Ovako možemo da uzmemo parne elemente od 2 do 6

Take[{a,b,c,d,f,g,h},{2,6,2}]

Izbor redova matrice

Razmotrimo sada složene liste. Najčešće radimo sa matricama. Evo primera matrice sa 4 kolone i 3 reda.

mat={{a,b,c,7},{d,e,f, 9},{g,h,i,10}};

mat//Grid

Izabrati samo drugi red

mat[[2]]

Napravimo podmatricu koja se sastoji od prvog i trećeg reda originalne matrice. To možemo da uradimo ovako:

{mat[[1]],mat[[3]]}

ili kraće

mat[[{1,3}]]

Grid[%]

Izabrati jednu ili više kolona

Pretpostavimo da želimo da izaberemo drugu kolonu. To možemo da uradimo ovako:

mat[[All,2]]

Ukoliko želimo da izaberemo kolonu 1 i 3, onda to možemo ovako

mat[[All,{1,3}]]

Grid[%]

Ako imamo još složenije liste, evo načina da izaberemo c:

{{a,b,{c,d}}}[[1,3,1]]

Primena Part u vezi sa izborom elemenata u složenim listama

Pretpostavimo da želimo da nađemo Pitagorine parove, to jest parove brojeva čija je suma kvadrata opet ceo broj. Evo jednog načina da to uradimo. Prvo napravimo

Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,20},{j,20}],1]

Izabraćemo samo one trojke za koje je poslednji element ceo broj. Pri tome ćemo ostaviti samo one parove za koje je prvi broj manji ili jednak drugom (kako ne bi bilo ponavljanja).

Select[Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,20},{j,20}],1],And[IntegerQ[#[[3]]],#[[1]]<=#[[2]]]&]

Pretpostavimo da nas interesuju samo pitagorini parove, to jest prva dva broja u svakoj trojci. Kako ćemo njih izvući?

Select[Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,20},{j,20}],1],And[IntegerQ[#[[3]]],#[[1]]<=#[[2]]]&][[All,1;;2]]

Još jedan primer

Razmotrimo slučajnu matricu realnih brojeva od -5 do 10 sa 4 kolone i 20 redova

data=RandomReal[{-5,10},{20,4}]

data//Grid

Naći redove za koje je suma elemenata u prvoj i trećoj koloni veća od sume elemenata u drugoj i četvrtoj koloni

Select[data,#[[1]]+#[[3]]>#[[2]]+#[[4]]&]

Koliko ima takvih redova?

Select[data,#[[1]]+#[[3]]>#[[2]]+#[[4]]&]//Length

Position nalazi položaj određenog elementa u listi

Position nalazi listu pozicija na kojima se nalazi neki element: Na primer, ovde imamo samo jedno d u matrici, na poziciji 2, 1:

Position[{{a,b,c},{d,e,f},{g,h,i}},d]

Ovo nam daje listu svih pozicija gde se pojavljuje x:

Position[{{x,y,x},{y,y,x},{x,y,y},{x,x,y}},x]

Evo pozicija gde se pojavljuje “a” u listi karaktera:

Position[Characters["The Wolfram Language"],"a"]

Naći pozicije gde se pojavljuje 0 u listi cifara broja 2^500:

IntegerDigits[2^500]

Flatten[Position[IntegerDigits[2^500],0]]

Naći najveće i najmanje elemente po nekom kriterijumu

TakeLargest i TakeSmallest uzimaju elemente liste prema veličini. Uzeti prvih 5 najvećih i pet najmanjih elemenata na listi:

TakeLargest[Range[20],5]

TakeSmallest[Range[20],5]

TakeLargestBy i TakeSmallestBy rade slično ali kada se na elemente primeni neka funkcija. Napravimo listu slučajnih trojki od 0 do 100

lista=RandomInteger[100,{50,3}]

Izaberite prvih 5 trojki koje imaju najveći drugi element u podlisti. Izaberite one koje imaju najmanji drugi element u podlisti.

TakeLargestBy[lista,#[[2]]&,5]

TakeSmallestBy[lista,#[[2]]&,5]

ReplacePart: zamena dela liste

Mada ćemo te stvari raditi kasnije detaljnije ovde uvodimo pojam ReplacePart. Koristimo neko pravilo. Ovde zamenjujemo deo na poziciji 3 sa x:

ReplacePart[{a,b,c,d,e,f,g},3->x]

a ovde deo na poziciji 3 sa x i deo na poziciji 5 sa y:

ReplacePart[{a,b,c,d,e,f,g},{3->x,5->y}]

Primetimo da u izrazu 3->x, 3 nije vrednost elementa liste nego redni broj elementa. Kasnije ćemo raditi i zamene gde ne koristimo redni broj neko oblik (pattern). Razmotrimo složemo listu. Ovako ćemo zameniti 3. element u prvoj podlisti (to je c) sa x.

ReplacePart[{{a,b,c,d,e,f,g},{32,21,g,f}},{1,3}->x]