# r-info09.txt in series norskesites.org/r-programmering by aristo t. # vi fortsetter med presisjonsstudium av slikt som hvordan bygge # funksjoner i R, vel vitende om at det kraftige knippe med # statistiske funksjoner inkl grafiske funksjoner er tilgjengelig # og vi kan da bruke det med mer forstaaelse, vi kan lese ogsaa # mer tekniske deler av dokumentasjonen med innsikt i betegnelsene. # det blir kanskje litt abstrakt men det er noe filosofisk # interessant ved de essensielle trigonometriske funksjonene som # vi har, og skal, arbeide med. her er litt oppsummering av det # vi vet om disse funksjonene, og noen refleksjoner som trekker # det videre til en viss ny formulering, og som setter det inn i # fysikk-kontekst. deretter gaar vi igang med mer programmering. # vi har tatt utgangspunkt i de siste r-info i at vi vil haandtere # velkjent trigonometri -- at man svinger en sirkel med radius 1 # rundt en akse i det velkjente x-y kartesianske koordinatsystem -- # og at man der finner x coordinaten ved cos eller cosinus eller # cosine eller hva vi kaller det, og y coordinaten ved sin, sinus, # eller sine. sirkelens totale omkrets er to ganger pi eller to # ganger 3.141592653582, der det er mulig aa bruke formler for # aa kalkulere endel flere desimaler hvis man vil (uttrykket # "uendelig mange desimaler" er mye brukt men meningsloest ut # fra min tallteori, som tar utgangspunkt i at det som er # grenseloest ikke kan fanges inn i begreper som dreier seg # om grenser, men maa, for at ideen skal vaere klar, regnes # som en forutsetning og ikke et resultat generert av grenser # eller av begrensete enheter slik som tall i en rekke). # siden x er 1 mens y er 0 baade ved start av en komplett sykel og # ved dens fullfoerelse, er cos(2*pi) = 1, mens sin(2*pi) = 0. vi skal # gaa litt videre med dette i et forsoek paa komplett aa frigjoere oss # fra gammeldags tenkning om trigometri og desimaltall, og se paa # det hele paa en litt uvanlig maate. # lengden av 'buen', the 'arc', er altsaa input til cos og sin. # siden x er cos, gir cos positive verdier opp til 90 grader, # som er pi halve. deretter gir cos negative verdier frem til # 270 grader, som er pi (180 grader) pluss en halv pi (90 grader), # altsaa 3/2 ganger pi. fra 3/2 og opp til 2 ganger pi (360 # grader) er cos igjen positiv. selve tallene den gir er dermed # identisk bortsett fra fortegn hvis vi deler sirklen i to, # og deler vi den i fire kvadranter ser vi at disse kvadrantene # speiler hverandre, slik at strengt tatt (uten at vi gjoer det) # kunne vi laget cos bare ut fra tallene til en eneste kvadrant, # saafremt vi regner litt foer og etter. men for raske rutiner # fokuserer vi paa enkelt oppslag i velbygde lister, og lar # listene heller vaere noe stoerre enn at vi bygger inn mange # ekstra regneregler i funksjonene. {dette gir mening naar man # skal lage slik som fotoeditoren 'gem' i g15, som kan rotere # fotos, og bruker nettopp den type lister vi lager her.} # sinus matcher i tall, men begynner altsaa ved 0 der cos begynner # ved 1, og fra 0 til pi er sinus positiv, og fra pi til to ganger # pi har sinus et fortegn. sett separat, gir sinus og cosins # identiske boelger men de er, som vi sier, "forskyvet i fase", # for sinus starter paa midten, saa gaar opp, saa ned, saa tilbake # til midten, mens cos starter paa toppen og ellers foelger # samme moenster. hvis vi lager en loop som plotter cos A, sin A # for en serie med tall fra 0 til to pi faar vi dermed en sirkel, # og slikt sett er disse to funksjonene med paa aa lappe sammen # tallteori med geometri. # gaar vi motsatte vei, ser vi at funksjonene ikke gir et entydig # resultat. de saakalte arc-cosine eller acos og arc-sine eller # asin burde gi to svar for hver input vi gir dem, for det er # alltid presist to vinkler som kan gi enhver x verdi, og alltid # presist to vinkler som kan gi enhver y verdi, siden sirklen # spenner rundt origo, og krysser enhver linje vi trekker innenfor # dens radius normalt til x to ganger, og den krysser enhver # linje vi trekker innenfor dens radius normalt to y ogsaa to # ganger. # dette har vaert loest i trigonometri ofte ved at man bruker # funksjonen atan2, eller arctangens, som tar imot baade verdien # til sinus, og verdien til cosinus, og gir en entydig vinkel # som output. men kikker vi litt paa det, ser vi at dette er # en litt 'heavy-handed' approach. vi trenger jo ikke mer enn # en eneste enkel informasjonsbite ekstra for aa vite eksakt vinkel # dersom vi har ENTEN cosinus ELLER sinus. den informasjonsbiten # vi trenger -- som kan representeres i data med 0 eller 1 -- # er hvorvidt den andre koordinaten er positiv eller har fortegn. # vaar kode er altsaa aa bruke "1" for "ja, den andre # koordinaten har et minustegn i seg". her er altsaa "1" et # symbol for sannhetsverdien 'true' mht til negativ verdi, # mens "0" er et symbol for sannhetsverdien 'false'. # med andre ord, hvis vi skal lage en meningsfyll, kompakt, # entydig acos, trenger vi to parametere: # vinkel = acos(x-coordinat, y-fortegn). # parameteret y-fortegn er "1" hvis y har et fortegn, er negativ. # dermed, gitt x-coordinaten i enhetssirklen, vil vi kunne # generere eksakt vinkel -- hvis y-fortegn "1", vil vi # anta at vinklen refererer til under x-aksen, og det er # entydig nok. saa, for eksempel, hvis vi skal finne acos(0, 1) # ser vi at vinkel er enten 90 eller 270, for dette er alle # muligheter, og 270 er 360 minus 90. dermed, naar y-fortegn # er symbolisert ved sannhetsverdien "1", slik som her, skal # vi la vaar acos returnere noe slikt som to pi minus den # vinklen vi ellers ville har returnert. # tilsvarende, hvis y er 0, kan vinklen vaere null eller pi, # derfor vil f.eks. asin(0, 1) gi pi, mens asin(0, 0) gi 0. # for andre verdier skal asin(y-coordinat, x-fortegn) generelt # speile vinklen rundt y-aksen, naar x-fortegn er markert "1". # for vinkler opp til 180 grader, eller pi, f.eks. 80 grader, # skal vi ha funksjonen slik at den returnerer noe slikt som # pi minus vinklen den ellers ville gitt naar x-fortegn er "1". # for vinkler over 180 grader, eller pi, f.eks. 280 grader, # skal funksjonen returnere noe slikt som forskjellen mellom # 360 grader eller to pi og vinklen, og deretter skal 180 # grader eller pi legges til. derfor skal vi gjoere noe slikt # som to pi minus vinklen, plus pi, som svar fra asin(v, 1) # i de tilfelle v er over pi. dette er litt mer men bare # litt mer digital kalkulering, det vil gaa fort. tegner # du opp de to speilingene blir det hele ganske enkelt. # dette virker kanskje litt plundrete og detaljert, men foelg # med: dette har en filosofisk betydning. vi skal ikke lage # disse funksjonene her i R, for de er tilgjengelig i PatMTNet, # men det har en verdi at vi snakker om dem her, for aa sette # denne type aritmetikk inn i et filosofisk lys. som bilde: # vi har en slags kilometer-teller som gaar over en halvsirkel # med asin(vinkel) og acos(vinkel), og for at den skal gaa # hele veien rundt -- og dermed bli en rotasjon, for # aa si det slik -- trengs KUN EN BIT. Null eller ett, og # dermed faar vi full rotasjon. ved at vi kopler vinkel, som # er et enkelt, vanlig tall med klart definert rekkevidde, # med en enkelt bit, faar vi noe som utspenner seg i ikke # mindre i to dimensjoner. det er sant at vi ikke har i dette # informasjon om lengden av pilen som gaar rundt, bare dens # retning, slik at vi er ikke hele veien til aa ha en vektor # (hvis vi med 'vektor' mener baade noe som har retning og # en variabel lengde), men vi har noe fundamental grafisk # mer enn et enkelt tall. og dette er i en viss forstand # det minste element man kan tenke seg i kvantefysikken, som # er med paa aa ligge til grunn for alle energi-utvekslinger # i den manifeste verden. dette elementet av rotasjon er # naermest fraktalt -- fraktal betyr at det staar et sted # mellom to dimensjoner -- fordi det er mer enn 1 dimensjon, # men likevel ikke det fulle 2 dimensjonale koordinatspunktet # som kan brukes til aa lage vakre figurer presentert i # to dimensjoner som et foto. # uansett, denne gangen skal vi bli ferdig med sinus og cosinus # og vi hopper over revers-utgaven av disse (som sagt, se # g15 pmn plattformen hvis du vil bruke dem), og i neste # r-info skal vi estimere kvadratrot. underveis laerer vi # mer om R -- hvordan lage en loop og hvordan skrive ut paa # tekstskjermen, og hvordan bruke 'if'. # saa gaar vi igang med mer programmering. vi kan begynne med # aa forfine arbeidet fra forrige gang. vi vil ha en cosinus # og en sinus funksjon som kan godta hvilke som helst # inngangstall, ikke bare innenfor 0..627, som er de 628 # tallene som med faktor 100 er en hel sirkel, to pi. skal # vi regne dette med tanke paa bruk i kompliserte grafiske # kalkyler for en datamaskin vil vi bruke en stoerre faktor, # og 10,000 er praktisk og gir gode tall. 3.1415926 runder vi # da til 3.1416 og det blir 31416, mens dobbelt av dette blir # 62832. her holder vi oss til faktor 100 men det tar bare # et sekund aa endre det til faktor 10000 naar vi trenger det. # hvis man skal forstaa noe av tallenes grunnlag i det # mentale begrep om uendelighet, maa man studere ideen om # tall som en form for essens, der vanskeligheten ligger i # aa definiere og begripe hva endelighet er, mens det # uendelige er utgangspunktet, det evige nu. men det er en # del av dette studium at man ser etter former, moenstre, # og ogsaa moenstre av bevegelse. titallssystemet kan man # argumentere for (se vaar 'theorems' section i arkiv til # yoga6d.org/economy.htm, arkiv side 10 har link til den) # som spesielt psykologisk naturlig og viktig, og ikke en # ren tilfeldighet. men i titallssystemet kan man se visse # siffer-rekkefoelger som man kan si, intuitivt, er 'talende'. # dette hjelper ogsaa aa huske dem. kontempler over 31416 # og 62832. kontempler over fibonacci rekken 2 3 5 8 13 21 # der de to siste tallene adderer seg (2+3=5, 3+5=8) til # aa bli det neste tallet, og se det forunderlige ved at # dette gradvis f.eks. ved 55/34 blir mer og mer det gylne # snitt ca 1.618 i proporsjon -- tast inn f.eks. round((55/34)*1000) # i R og 1618 er resultatet, med heltallsskala 1000. # vi beorer her ved meditative proporsjoner som er naturlige # baade i naturlige spiraler og i skjoennhetsmaleri og foto. # i hvilken grad intuisjoner over tall faktisk holder maal # skal vi la vaere uuttalt, men det er i alle fall # del av at man faar et personlig forhold til tallene -- # noe som har vaert et gjennomgangstema i disse R-tekster, # mer eller mindre, gi og med at grafisk fremstilling er # en maate aa se moenstre (ogsaa statistiske moenstre) # i tall. # vi vil gjerne at dersom tallet er negativt, legges til # et tilstrekkelig antall 628 slik at tallet blir til 0..627 # foer vi gjoer en "lookup" i listen vaar; og dersom tallet # er stoerre enn 627 vil vi fjerne et tilstrekkelig antall 628 # slik at tallet blir til 0..627. dette gjoer at vi kan # bruke vaare egne heltallsfunksjoner for aa enkelt plotte # grafer som bruker stoerre spenn av inngangsverdier, slik # at vi gaar enda naermere til de klassiske funksjonene. # merk at vi gjoer ingenting i programmeringen naa som ikke # foerst er snakket om, tenkt paa, gjort begrepsmessig klart. # i formuleringen av firth234 konseptualiserte jeg dette som # 'first-hand relationship to data' og etterhvert ble det til # uttrykket 'first-hand programming' som jeg innfoerte over # flere aar og stadig finner glede i. min inspirasjon til # bruk av uttrykket var en kommentar i en bok fra den indiske # tenkeren J. Krishnamurti om viktigheten av 'not to have # a second-hand mind'. dette kan vaere viktig aa repetere i # disse tider der enkelte tendenser til overbruk av store # datamengder og til ureflektert tro paa statistikk uten # innsikt i dens bias maa imoetegaas gjennom selvstendighet. # jeg skulle tro at idag er det mange som vet hva som menes # med 'first-hand programming', men da jeg kom med dette # var det helt nytt, meg bekjent. la oss da lage vaare # foerste-haands heltallcosinus og heltallsinus. # i neste r-info, som fullfoerer fokus paa trigonometriske # funksjoner og som tilbyr enda mer innsikt i hvordan bruke # R i aritmetrisk detail, lager vi vaar egen kvadratrot # ogsaa basert paa liste, der litt fingrubling maa til for # at listen ikke skal bli enormt stor selv om vi skal # estimere kvadratroten over et stort spenn av verdier. # vi bruker altsaa en annen enhetssirkel: den har radius # hundre, naar vi bruker faktor hundre, og derfor brukes # hundre pi der vi ellers ville brukt pi, osv. # i neste funksjon er %% aa lese som 'remainder', # f.eks. er 629 %% 628 lik 1, mens 630 %% 628 lik 2. # remainder eller modulus, ofte ogsaa kalt 'mod', # er en funksjon som greit fikserer et tall som # kan variere mye innenfor en bestemt smal vidde. # videre, %/% brukes i neste funksjon. dette er deling. # forskjellen mellom / (desimaldeling) og %/% er # at sistnevnte inneholder avrunding til hele tall. # igjen, vi kunne lagret dataene paa disk, og startet # R paa nytt, og brukt dataene uten aa bruke sinus # i det hele tatt. men foerst gjoer vi det mer interaktivt # slik at vi ser presist hva som skjer, hvertfall # hvis vi analyserer det. vi skal vaere klar over # at modulus, eller %% som den heter i R, lett # gir null som resultat. dette skjer hver gang # en tilsvarende deling ville ha null 'rest'. # men naar vi bruker den mest vanlige typen array # i R, maa vi passe paa at vi starter med 1, for # i R er 1 det foerste elementet, normalt. # saa vi lager wholesine og wholecosine med endel forfining # og grundighet, slik at vi laerer mest mulig om # finprogrammering i R i samme slengen. det er dog litt # finuerligheter! i forrige r-info tror jeg at vi saavidt # nevnte dette med at R starter arrays eller hva vi kaller dem # ved aa telle fra 1, ikke fra 0. men vi er kanskje kjent med # at det er vanlig at man kan gi 0 til baade sine og cosine. # hvis vi har en array some heter wholesinearray maa # vi passe paa at den brukes ordentlig, det finnes mao # normalt ikke noe element som heter wholesinearray[0]. # vi kan forskyve alle elementer, slik at wholesinearray[1] # har svaret for hva sinus 0 er, og [2] har svaret for hva # sinus 1 er, og saa videre opp til [628], som har svaret # for hva sinus 627 er. fordi ogsaa R har en avansert # 'remainder' funksjon som takler negative tall -- hvilket # ikke er vanlig for 'remainder' eller 'mod' eller modulus # eller hva man kaller det (se beskrivelse ovenfor), # kunne man gjoere noe slikt som dette: # wholesine <- function( wholeangle ) { # return( wholesinearray[ (wholeangle %% 628) + 1 ] ) # plot(wholesine(1:(5*628))) # for naar vi har en funksjon som bare er en enkel formel, # er det lett aa gi den en input av typen 1:n. da maa vi # bygge opp wholesinearray med en viss forskyvning. men det # er likevel en verdi i at vi gaar langsommere frem. blant # annet er trigonometri ikke her hovedmaalsettingen, # det dreier seg om aa laere ulike muligheter for # statistisk relevant programmering i R. videre kan det # vaere at du vil bruke et annet programmeringsspraak # som har andre kjennetegn for hvordan lister er formattert, # pluss at det kanskje er en modulus som gir negative tall # hvis den fores med noe negativt, og dermed oppfoerer seg # helt annerledes enn &&-operatoren ovenfor for disse # tall. etter endel frem og tilbake bestemte jeg meg for # at det blir mest laererikt om vi bygger opp det hele # trinn for trinn, og uten aa lene oss paa den uvanlig # avanserte modulus-funksjonen -- men bare bruke den for # positive verdier. # start opp R og copy og paste alle disse linjene frem # til der jeg har skrevet "*** close sinus plot vinduet", # saa skal vi droefte hva som foregaar her etterpaa. # det vil hvis du bruker noe tid med det etterhvert bli # lysende klart! merk at R tillater at du skriver # flere ulike utsagn etter hverandre paa samme linje # hvis du skiller dem med semikolon; men det er ikke # noe krav til semikolon naar du har tilstrekkelig mange # linjeskift lagt inn. generating_sine_values <- function(inputx=31416, faktor=10000) { return( round(faktor * sin(inputx / faktor)) ) } generating_cosine_values <- function(inputx=31416, faktor=10000) { return( round(faktor * cos(inputx / faktor)) ) } normaliseangle <- function( wholeangle ) { if (wholeangle > 628) wholeangle = (wholeangle %% 628) if (wholeangle < 1) return (wholeangle + (628* ((abs(wholeangle) %/% 628) + 1))) return (wholeangle) } wholesinearray <- generating_sine_values(1:628, 100) wholecosinearray <- generating_cosine_values(1:628, 100) wholesine <- function( wholeangle ) { return( wholesinearray[ normaliseangle(wholeangle) ] ) } wholecosine <- function( wholeangle ) { return( wholecosinearray[ normaliseangle(wholeangle) ] ) } lagsinusplotteverdier <- function(antall = 628) { plotteverdier <- 1:antall for (i in 1:antall) { plotteverdier[i] = wholesine(i) } return(plotteverdier) } lagcosinusplotteverdier <- function(antall = 628) { plotteverdier <- 1:antall for (i in 1:antall) { plotteverdier[i] = wholecosine(i) } return(plotteverdier) } nyeverdier <- lagsinusplotteverdier(628*5) plot(nyeverdier) # *** close sinus plot vinduet, deretter proev nyeverdier <- lagcosinusplotteverdier(628*5) plot(nyeverdier) # *** close cosinus plot vinduet, kikk paa noen tall ved at du # paster inn denne veldig enkle print-ut funksjonen av noen # ganske tilfeldig valgte tall-eksempler: noenverdier <- function() { for (i in 1:10) { i5 <- i*333 - 1000 print(sprintf("Wholesine for %i er %i. ", i5, wholesine(i5))) } } noenverdier() # det er mange linjer ovenfor men begynn paa toppen og kikk lenge # paa hver enkelt og du vil se at det er ingenting komplisert noe # sted, hvertfall med litt forklaringer her og der. # generate_sine_values og generate_cosine_values er samme sak # som i forrige r-info. normaliseangle er ny. det den gjoer er # at den kikker paa vinklen. her brukes if ( .. ) og vi kunne ogsaa # hatt en struktur av typen if ( .. ) { .. } else if ( .. ) { .. } # else { .. } der vi har en sammenligning i ( .. ) og en eller # annen handling der vi skriver { .. } -- eller en bunte handlinger # hvis vi pakker dem inn i { og }. # for sammenligning om hvorvidt tall er like bruk == og ikke =. # bruk ogsaa f.eks. < (er det mindre enn?) > (er det stoerre enn?) # <= (er det mindre enn eller likt?) og => (stoerre enn eller likt?) # -- og en slik betingelse skal gi TRUE eller FALSE som output og # ut fra dette bestemmes den videre flyten i utfoeringen av funksjonen. # R tilbyr noen andre varianter ogsaa. # normaliseangle soerger for at vi aldri faar ut vinkel 0. hvis # man gir den vinkel 0, kommer 628 ut. den bruker deling av # heltallstypen, %/% til forskjell fra deling med desimaler, /. # hvis vinkel 0 eller et negativt tall gis den, legges det til # et antall 628 slik at faar vinklen til aa bli positiv. # paa den annen side, hvis vinklen > 628 brukes remainder eller # modulus funksjonen, %%. men merk at siden %% kan gi null som # resultat, gjoer funksjonen seg ikke umiddelbart ferdig etter # at %% er brukt, den sjekker deretter om vinklen er mindre enn 1, # og fikser paa resultatet hvis noedvendig. altsaa en normalisering # av vinklen. normaliseangle ser komplisert ut men det er gjennom # litt proeving og feiling at man finner ut av den. den bruker # funksjonen abs( .. ) som fjerner minustegnet til et negativt tall. # naar det staar noe slikt som aaa <- aaa + 5 betyr det at # variablen aaa mottar en ny verdi, og den nye verdien staar # paa hoeyre side, den er den tidligere verdien pluss 5. # vi bruker <- naar vi skaper variabler og ogsaa gir dem nye # verdier. naar vi vil fremheve at variablen allerede finnes # brukes = istedet. vi kan lage en ny array f.eks. ved alfa1 <- 1:8 # (som ogsaa initialiserer tallene i arrayen til 1..8) # men naar vi skal gi verdien 33 til det femte elementet i alfa1 # kan vi skrive noe slikt som alfa1[5] = 33. # slik funksjonen er skrevet finner du at den har 'return(..)' # mer enn et sted. reglen er at funksjonen ser seg ferdig # naar den stoeter paa den foerste return, og avslutter da # med aa gi denne verdien videre til 'verden' (dvs den som # kalte funksjonen). den foerste return er betinget av en 'if', # saa den vil ikke alltid brukes, derfor maa vi passe paa at # det er en return til. man kan skrive dette som if .. else # og slikt, eller man kan ha bare en return paa slutten, men # dette er en litt raskere maate. enda raskere er det at man # dropper 'normaliseangle' og fokuserer paa aa bruke bare de # helt korrekte verdier, eller lager en miniversjon av # normalise som konverterer 0 til 628. # ok., ikke lysende klart skrevet, men det er analyserbart, # det hele, hvis du tar funksjonen fra hverandre, endrer paa # noe, proever aa skrive den paa ulike maater. # deretter lager vi array'en eller listen eller vektoren eller # hva vi kaller det (i r's dokumentasjon defineres slike ord # forskjellig men i dagligtalen er disse begreper naturligvis # ikke alltid skarpt definerte). vi setter opp listen med tall # ved generating_sine_values(1:628, 100) og slikt, som bevisst # begynner paa 1, og slutter paa 628. denne listen vil ha sinus # til 1 (i valgt skala) paa plass [1], uten noe forskyvning. # dette er estetisk bedre og psykologisk klarere enn forskyvning, # selv om det altsaa er andre veier til tilsvarende output. # takket vaere at vi har funksjonen normaliseangle vil vi likevel # kunne fore vaar sinus og cosinus med 0 og faa det forventete # resultat, som vil vaere identisk med resultatet for 628, og # vi kan gi hvilken som helst tall og den vil hele tiden # normalisere til 1..628 og dermed ikke gi oss en indeks som # gaar utenfor vaart array. vaar funksjon, som slaar opp i # vaar liste gjennom normaliseangle, er altsaa: # # wholesine <- function( wholeangle ) { # return( wholesinearray[ normaliseangle(wholeangle) ] ) # } # # vi vil gjerne plotte fra 1 til f.eks. 5*628, men siden vi # har en funksjon som ikke bare en formel, men som inneholder # flere handlinger, boer vi gjoere dette trinnvis, gjennom # en loop som vi selv lager. hadde det vaert en enkel formel # kan vi bare sette 1:(5*628) inn i funksjonen og vips har # vi listen med svar. men denne funksjonen trenger litt mer # omsorg naar vi skal bruke den. derfor: # lagsinusplotteverdier <- function(antall = 628) { # plotteverdier <- 1:antall # for (i in 1:antall) { # plotteverdier[i] = wholesine(i) # } # return(plotteverdier) # } # denne funksjonen forventer at du gir et antall til den -- # det kan utmerket godt vaere 5*628 som du gir til den -- # og deretter vil den gjenta, "loope", der i er telleren. # uttrykket er for (i in 1:(5*628)) { .. } og i vil gaa # trinnvis opp fra 1 til 5*628 eller hva vi setter som # maksimum, og hver gang vil handlingen inne i { .. } # utfoeres. paa den maaten kaller vi vaar wholesine # 5*628 ganger. dette lagres i en liste som vi oppretter # inne i funksjonen og returnerer til den som kalte # funksjonen. naar vi saa gjoer # nyeverdier <- lagsinusplotteverdier(628*5) # plot(nyeverdier) # nyeverdier <- lagcosinusplotteverdier(628*5) # plot(nyeverdier) # oppnaar vi at arrayet 'nyeverdier' fylles med de svar # fra vaare nye funksjoner som vi vil. # funksjonen 'noenverdier' skriver ut i en lignendne loop # som bruker for (i in 1:n) { .. } for aa gjenta noe # et bestemt antall ganger. det som gjentas er # print(sprintf("Wholesine for %i er %i. ", i5, wholesine(i5))) # og det skal leses slik: # print ut en tekst som bestaar av uttrykket Wholesine for xxx er xxx # der xxx og xxx henholdsvis byttes ut med i5 og wholesine(i5). # hver gang man bruker sprintf er det for aa blande f.eks. # tekst med tall. i sprintf vil det gjerne finnes en eller # flere %-tegn fulgt av en bokstav. for denne type tall brukes # %i. bokstaven i etter %-tegnet betyr vel 'integer'. det # er en annen i, for aa si det slik, enn den telleren som # vi bruker. det kunne staatt sprintf("tallet er %i.", 5), # og da tar tallet 5 plassen for %i. # vi faar mer tenkning om tall og avsluttende kommentarer i neste. det # er likevel litt til vi kan laere ved aa bygge paa det vi har gjort. # her vises hvordan vi kan lagre sine og cosine verdiene paa disk. # det andre knippet linjer viser hvordan vi kan hente dem frem igjen. # avslutt og start opp R etter 'write' linjene, og vi faar testet at # vi kan plotte sinus og cosinus fra diskdata: generating_sine_values <- function(inputx=31416, faktor=10000) { return( round(faktor * sin(inputx / faktor)) ) } generating_cosine_values <- function(inputx=31416, faktor=10000) { return( round(faktor * cos(inputx / faktor)) ) } wholesinearray <- generating_sine_values(1:628, 100) wholecosinearray <- generating_cosine_values(1:628, 100) write(wholesinearray, "sinedata.txt") write(wholecosinearray, "cozydata.txt") # dette forutsetter at du har skrive-tilgang til den delen # av disken du starter R i. hvis ikke, lag et lengre # filnavn av typen /home/Regina/documents/cozydata.txt # eller noe annet hvis din PC's 'hjemmefolder' er noe annet. # bruk de samme navnene i det som foelger. start R paa # nytt, og: wholesinearray=scan("sinedata.txt") wholecosinearray=scan("cozydata.txt") normaliseangle <- function( wholeangle ) { if (wholeangle > 628) wholeangle = (wholeangle %% 628) if (wholeangle < 1) return (wholeangle + (628* ((abs(wholeangle) %/% 628) + 1))) return (wholeangle) } wholesine <- function( wholeangle ) { return( wholesinearray[ normaliseangle(wholeangle) ] ) } wholecosine <- function( wholeangle ) { return( wholecosinearray[ normaliseangle(wholeangle) ] ) } lagsinusplotteverdier <- function(antall = 628) { plotteverdier <- 1:antall for (i in 1:antall) { plotteverdier[i] = wholesine(i) } return(plotteverdier) } lagcosinusplotteverdier <- function(antall = 628) { plotteverdier <- 1:antall for (i in 1:antall) { plotteverdier[i] = wholecosine(i) } return(plotteverdier) } nyeverdier <- lagsinusplotteverdier(628*5) plot(nyeverdier) # der fikk vi det til helt uten bruk av 'sin' # i samme sesjon! dette er altsaa, innen den # skala vi velger, en fungerende heltalls-sinus. # *** close sinus plot vinduet, deretter proev nyeverdier <- lagcosinusplotteverdier(628*5) plot(nyeverdier) # vips har vi laget foerste del av vaar egen # heltalls trigonometri, og vi klarte aa bruke # funksjonene til aa lage vakre kurver uten aa ha # brukt 'sin' eller 'cos' i samme program. # deretter, for foerste-haands forhold til dataene, # sjekk hvordan sinedata.txt og cozydata.txt ser ut # hvis du aapner i en tekstbehandler eller browser -- # en bunte med tall, bare noen paa hver linje: # det kunne ikke vaere enklere. # variasjoner: eksperimenter med ulike inngangstall # til f.eks. disse: nyeverdier <- lagsinusplotteverdier(25) pie(nyeverdier) # og, etter at rammen er lukket, nyeverdier <- lagsinusplotteverdier(8*628) barplot(nyeverdier) # i ubuntu presser du 'prt sc' knappen hvis du vil # lagre skjermbildet, og du kan naturligvis bruke # en image editor for aa paste paa tekst, hvis du # vil ha andre muligheter enn de eksemplifisert i # de foerste av vaare r-info'er vedroerende # tekst-printing paa bilde. hvis du vil ogsaa bruke # require(grid) funksjonene skulle du naa ha rikelig # med innsikt i hvordan modifisere parametere til # de egnete grid-plotte-funksjoner til aa ta imot # data f.eks. fra dette arbeidet vi naa har gjort. # gjennom den kompetansen de siste r-info's har gitt # deg i funksjon-input-output og arrays og slikt, # vil grid-pakken og andre deler av R vaere langt # mer transparent og lettfattelig. # saa det er nevnt, finnes det i mange spraak muligheten # til aa pakke sammen data og funksjoner. dette kan gjoeres # paa ulike maater. du vil ofte se notasjoner av typen # navn1.navn2 eller navn1::navn2 naar ting er pakket # slikt, og i enkelte sammenhenger navn1->navn2. det # ene navnet viser da til pakken, og det andre navnet # viser til et element i pakken, og det element er # i noen tilfeller variabler, og i andre tilfeller # egne funksjoner. verdien av dette staar nok ikke i # forhold til de fancy beskrivelser som noen ganger gis # av enkelte former for pakking av data og programmer # (noen snakker om "objekt-orientering", men dette er # etter min mening -- og Kristen Nygaard, som med # Ole Johan Dahl skapte uttrykket, fikk meg ikke til # aa skifte mening etter mange samtaler med han -- # et altfor generelt uttrykk til aa dekke det det # dreier seg om, et hierarki av data/program-pakker). # R har visse muligheter for slik pakking, og i mange # sammenhenger betyr dette ikke noe annet enn at # navnene for data og funksjoner blir litt lengre, # og har punktum eller kolon i seg. i noen sammehenger # trekkes ideen om 'samtidig aktiverte objekter' frem # som et slags fremskritt i databransjen, men det er # ingenting man kan gjoere med disse saakalte 'objekter' # som man ikke kan gjoere med den type programlinjer # vi har vaert gjennom i denne r-info. det eneste # ekstra-element man behoever for virkelig aa gjoere # det hele fort og elegant, med lavt forbruk av # datamaskinressurser, er noe som klassisk sett kalles # 'pekere' men som vi i g15 pmn sammenheng kaller # for 'warps', for det er mer dynamisk og umiddelbart. # dette skal vi ikke gaa inn paa her, men vi tok med # denne kommentaren for aa faa det sagt: med et # saakalt 'algoritmisk' anlagt spraak -- og hver # funksjon kan sies aa vaere en algoritme -- kan du # gjoere i prinsipp alt man kan gjoere med det mye # hyper-blaserte "objekt-orientering". mao, objekt- # orientering, slik java er full av, er for det meste # noe blah-blah som betyr mye ekstra koding. det finnes # evangelister innen objekt-orientering som er uenig # med meg, men spoer om de har laget eget operativsystem # eller bygget et spraak fra grunnen, -- folk som digger # objekt-orientering er som regel folk som ikke har # laget saa mye selv. de lener seg paa andres objekter. # kristen nygaard kan ikke lastes for at hans hobby- # prosjekt paa regnecentralen paa 1960-tallet ble saa # populaert at det ble hysteri rundt det. det var en # meget lite fruktbar ide i forhold til hvilken dominans # det fikk, hele apple og windows og alt ble bygget # rundt den type konsepter, og det skapte en avstand # mellom datafolk og andre som var paa vei til aa # begynne aa laere seg algoritmisk programmering at # det var saa mye blah-blah om 'objekt-orientering'. # i disse dager begynner flere og flere aa se dette, # og slikt som java er ikke saa viktig lenger. # R, i likhet med Perl og tradisjonell enkel Lisp # og ikke minst Forth og visse former for Pascal # og de fleste former for C har alle algoritmisk # tilnaerming, og de tillater i ulike grad det som # vi videreforedler i g15, nemlig de omtalte warps. # all right!